Merge remote-tracking branch 'upstream/master' into StackVariable

Conflicts:
      change-notes/1.24/analysis-cpp.md
      cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql
This commit is contained in:
Jonas Jensen
2019-11-28 17:51:20 +01:00
308 changed files with 6719 additions and 1904 deletions

View File

@@ -15,7 +15,10 @@ import cpp
from ExprInVoidContext op
where
op instanceof EQExpr
or
op.(FunctionCall).getTarget().hasName("operator==")
not op.isUnevaluated() and
(
op instanceof EQExpr
or
op.(FunctionCall).getTarget().hasName("operator==")
)
select op, "This '==' operator has no effect. The assignment ('=') operator was probably intended."

View File

@@ -84,8 +84,10 @@ where
not peivc.getEnclosingFunction().isDefaulted() and
not exists(Macro m | peivc = m.getAnInvocation().getAnExpandedElement()) and
not peivc.isFromTemplateInstantiation(_) and
not peivc.isFromUninstantiatedTemplate(_) and
parent = peivc.getParent() and
not parent.isInMacroExpansion() and
not peivc.isUnevaluated() and
not parent instanceof PureExprInVoidContext and
not peivc.getEnclosingFunction().isCompilerGenerated() and
not peivc.getType() instanceof UnknownType and

View File

@@ -1,3 +1,3 @@
bool not_in_range(T *ptr, T *ptr_end, size_t a) {
return ptr + a >= ptr_end || ptr + a < ptr; // BAD
bool not_in_range(T *ptr, T *ptr_end, size_t i) {
return ptr + i >= ptr_end || ptr + i < ptr; // BAD
}

View File

@@ -1,3 +1,3 @@
bool not_in_range(T *ptr, T *ptr_end, size_t a) {
return a >= ptr_end - ptr; // GOOD
bool not_in_range(T *ptr, T *ptr_end, size_t i) {
return i >= ptr_end - ptr; // GOOD
}

View File

@@ -4,29 +4,27 @@
<qhelp>
<overview>
<p>
The expression <code>ptr + a &lt; ptr</code> is equivalent to <code>a &lt;
0</code>, and an optimizing compiler is likely to make that replacement,
thereby removing a range check that might have been necessary for security.
If <code>a</code> is known to be non-negative, the compiler can even replace <code>ptr +
a &lt; ptr</code> with <code>false</code>.
When checking for integer overflow, you may often write tests like
<code>p + i &lt; p</code>. This works fine if <code>p</code> and
<code>i</code> are unsigned integers, since any overflow in the addition
will cause the value to simply "wrap around." However, using this pattern when
<code>p</code> is a pointer is problematic because pointer overflow has
undefined behavior according to the C and C++ standards. If the addition
overflows and has an undefined result, the comparison will likewise be
undefined; it may produce an unintended result, or may be deleted entirely by an
optimizing compiler.
</p>
<p>
The reason is that pointer arithmetic overflow in C/C++ is undefined
behavior. The optimizing compiler can assume that the program has no
undefined behavior, which means that adding a positive number to <code>ptr</code> cannot
produce a pointer less than <code>ptr</code>.
</p>
</overview>
<recommendation>
<p>
To check whether an index <code>a</code> is less than the length of an array,
simply compare these two numbers as unsigned integers: <code>a &lt; ARRAY_LENGTH</code>.
To check whether an index <code>i</code> is less than the length of an array,
simply compare these two numbers as unsigned integers: <code>i &lt; ARRAY_LENGTH</code>.
If the length of the array is defined as the difference between two pointers
<code>ptr</code> and <code>p_end</code>, write <code>a &lt; p_end - ptr</code>.
If a is <code>signed</code>, cast it to <code>unsigned</code>
in order to guard against negative <code>a</code>. For example, write
<code>(size_t)a &lt; p_end - ptr</code>.
<code>ptr</code> and <code>p_end</code>, write <code>i &lt; p_end - ptr</code>.
If <code>i</code> is signed, cast it to unsigned
in order to guard against negative <code>i</code>. For example, write
<code>(size_t)i &lt; p_end - ptr</code>.
</p>
</recommendation>
<example>
@@ -43,14 +41,14 @@ overflows and wraps around.
<p>
In both of these checks, the operations are performed in the wrong order.
First, an expression that may cause undefined behavior is evaluated
(<code>ptr + a</code>), and then the result is checked for being in range.
(<code>ptr + i</code>), and then the result is checked for being in range.
But once undefined behavior has happened in the pointer addition, it cannot
be recovered from: it's too late to perform the range check after a possible
pointer overflow.
</p>
<p>
While it's not the subject of this query, the expression <code>ptr + a &lt;
While it's not the subject of this query, the expression <code>ptr + i &lt;
ptr_end</code> is also an invalid range check. It's undefined behavor in
C/C++ to create a pointer that points more than one past the end of an
allocation.

View File

@@ -3,9 +3,20 @@
"qhelp.dtd">
<qhelp>
<overview>
<p>Using TLS or SSLv23 protool from the boost::asio library, but not disabling deprecated protocols or disabling minimum-recommended protocols.</p>
<p>Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols may expose the software to known vulnerabilities or permit weak encryption algorithms to be used. Disabling the minimum-recommended protocols is also flagged.</p>
</overview>
<recommendation>
<p>When using the TLS or SSLv23 protocol, set the <code>no_tlsv1</code> and <code>no_tlsv1_1</code> options, but do not set <code>no_tlsv1_2</code>. When using the SSLv23 protocol, also set the <code>no_sslv3</code> option.</p>
</recommendation>
<example>
<p>In the following example, the <code>no_tlsv1_1</code> option has not been set. Use of TLS 1.1 is not recommended.</p>
<sample src="TlsSettingsMisconfigurationBad.cpp"/>
<p>In the corrected example, the <code>no_tlsv1</code> and <code>no_tlsv1_1</code> options have both been set, ensuring the use of TLS 1.2 or later.</p>
<sample src="TlsSettingsMisconfigurationGood.cpp"/>
</example>
<references>
<li>
<a href="https://www.boost.org/doc/libs/1_71_0/doc/html/boost_asio.html">Boost.Asio documentation</a>.

View File

@@ -1,6 +1,6 @@
/**
* @name Boost_asio TLS Settings Misconfiguration
* @description Using TLS or SSLv23 protool from the boost::asio library, but not disabling deprecated protocols or disabling minimum-recommended protocols
* @description Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols, or disabling minimum-recommended protocols.
* @kind problem
* @problem.severity error
* @id cpp/boost/tls_settings_misconfiguration

View File

@@ -0,0 +1,8 @@
void useTLS_bad()
{
boost::asio::ssl::context ctx(boost::asio::ssl::context::tls);
ctx.set_options(boost::asio::ssl::context::no_tlsv1); // BAD: missing no_tlsv1_1
// ...
}

View File

@@ -0,0 +1,8 @@
void useTLS_good()
{
boost::asio::ssl::context ctx(boost::asio::ssl::context::tls);
ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); // GOOD
// ...
}

View File

@@ -4,13 +4,22 @@
<qhelp>
<overview>
<p>Using boost::asio library but specifying a deprecated hardcoded protocol.</p>
<p>Using a deprecated hardcoded protocol instead of negotiting would lock your application to a protocol that has known vulnerabilities or weaknesses.</p>
</overview>
<recommendation>
<p>Only use modern protocols such as TLS 1.2 or TLS 1.3.</p>
</recommendation>
<example>
<p>In the following example, the <code>sslv2</code> protocol is specified. This protocol is out of date and its use is not recommended.</p>
<sample src="UseOfDeprecatedHardcodedProtocolBad.cpp"/>
<p>In the corrected example, the <code>tlsv13</code> protocol is used instead.</p>
<sample src="UseOfDeprecatedHardcodedProtocolGood.cpp"/>
</example>
<references>
<li>
<a href="https://www.boost.org/doc/libs/1_71_0/doc/html/boost_asio.html">Boost.Asio documentation</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,7 @@
void useProtocol_bad()
{
boost::asio::ssl::context ctx_sslv2(boost::asio::ssl::context::sslv2); // BAD: outdated protocol
// ...
}

View File

@@ -0,0 +1,7 @@
void useProtocol_good()
{
boost::asio::ssl::context cxt_tlsv13(boost::asio::ssl::context::tlsv13);
// ...
}

View File

@@ -84,10 +84,10 @@ predicate hasZeroParamDecl(Function f) {
}
// True if this file (or header) was compiled as a C file
predicate isCompiledAsC(Function f) {
exists(File file | file.compiledAsC() |
file = f.getFile() or file.getAnIncludedFile+() = f.getFile()
)
predicate isCompiledAsC(File f) {
f.compiledAsC()
or
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
}
from FunctionCall fc, Function f, Parameter p
@@ -95,7 +95,7 @@ where
f = fc.getTarget() and
p = f.getAParameter() and
hasZeroParamDecl(f) and
isCompiledAsC(f) and
isCompiledAsC(f.getFile()) and
not f.isVarargs() and
not f instanceof BuiltInFunction and
p.getIndex() < fc.getNumberOfArguments() and

View File

@@ -24,10 +24,10 @@ predicate hasZeroParamDecl(Function f) {
}
// True if this file (or header) was compiled as a C file
predicate isCompiledAsC(Function f) {
exists(File file | file.compiledAsC() |
file = f.getFile() or file.getAnIncludedFile+() = f.getFile()
)
predicate isCompiledAsC(File f) {
f.compiledAsC()
or
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
}
from FunctionCall fc, Function f
@@ -36,7 +36,7 @@ where
not f.isVarargs() and
not f instanceof BuiltInFunction and
hasZeroParamDecl(f) and
isCompiledAsC(f) and
isCompiledAsC(f.getFile()) and
// There is an explicit declaration of the function whose parameter count is larger
// than the number of call arguments
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |

View File

@@ -25,10 +25,10 @@ predicate hasZeroParamDecl(Function f) {
}
// True if this file (or header) was compiled as a C file
predicate isCompiledAsC(Function f) {
exists(File file | file.compiledAsC() |
file = f.getFile() or file.getAnIncludedFile+() = f.getFile()
)
predicate isCompiledAsC(File f) {
f.compiledAsC()
or
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
}
from FunctionCall fc, Function f
@@ -36,7 +36,7 @@ where
f = fc.getTarget() and
not f.isVarargs() and
hasZeroParamDecl(f) and
isCompiledAsC(f) and
isCompiledAsC(f.getFile()) and
exists(f.getBlock()) and
// There must not exist a declaration with the number of parameters
// at least as large as the number of call arguments

View File

@@ -16,28 +16,28 @@
import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.models.implementations.Memcpy
import semmle.code.cpp.models.interfaces.ArrayFunction
class MallocCall extends FunctionCall {
MallocCall() { this.getTarget().hasGlobalOrStdName("malloc") }
Expr getAllocatedSize() {
if this.getArgument(0) instanceof VariableAccess
then
exists(StackVariable v, ControlFlowNode def |
definitionUsePair(v, def, this.getArgument(0)) and
exprDefinition(v, def, result)
)
else result = this.getArgument(0)
}
Expr getAllocatedSize() { result = this.getArgument(0) }
}
predicate terminationProblem(MallocCall malloc, string msg) {
malloc.getAllocatedSize() instanceof StrlenCall and
not exists(FunctionCall fc, MemcpyFunction memcpy, int ix |
DataFlow::localExprFlow(malloc, fc.getArgument(ix)) and
fc.getTarget() = memcpy and
memcpy.hasArrayOutput(ix)
// malloc(strlen(...))
exists(StrlenCall strlen | DataFlow::localExprFlow(strlen, malloc.getAllocatedSize())) and
// flows into a null-terminated string function
exists(ArrayFunction af, FunctionCall fc, int arg |
DataFlow::localExprFlow(malloc, fc.getArgument(arg)) and
fc.getTarget() = af and
(
// null terminated string
af.hasArrayWithNullTerminator(arg)
or
// likely a null terminated string (such as `strcpy`, `strcat`)
af.hasArrayWithUnknownSize(arg)
)
) and
msg = "This allocation does not include space to null-terminate the string."
}

View File

@@ -1,7 +1,7 @@
/**
* @name Conditionally uninitialized variable
* @description When an initialization function is used to initialize a local variable, but the
* returned status code is not checked, the variable may be left in an uninitialized
* @description An initialization function is used to initialize a local variable, but the
* returned status code is not checked. The variable may be left in an uninitialized
* state, and reading the variable may result in undefined behavior.
* @kind problem
* @problem.severity warning

View File

@@ -464,7 +464,7 @@ private predicate simpleParameterFlow(
) {
throughFlowNodeCand(node, config) and
p = node and
t = getErasedRepr(node.getType()) and
t = getErasedNodeType(node) and
exists(ReturnNode ret, ReturnKind kind |
returnNodeGetEnclosingCallable(ret) = p.getEnclosingCallable() and
kind = ret.getKind() and
@@ -475,21 +475,21 @@ private predicate simpleParameterFlow(
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localFlowStep(mid, node, config) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, _, config) and
additionalLocalFlowStep(mid, node, config) and
t = getErasedRepr(node.getType())
t = getErasedNodeType(node)
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localStoreReadStep(mid, node) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// value flow through a callable
@@ -497,7 +497,7 @@ private predicate simpleParameterFlow(
exists(Node arg |
simpleParameterFlow(p, arg, t, config) and
argumentValueFlowsThrough(arg, node, _) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// flow through a callable
@@ -989,7 +989,9 @@ private class CastingNode extends Node {
*/
private predicate flowCandFwd(Node node, boolean fromArg, AccessPathFront apf, Configuration config) {
flowCandFwd0(node, fromArg, apf, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), apf.getType())
else any()
}
/**
@@ -1010,7 +1012,7 @@ private class AccessPathFrontNilNode extends Node {
}
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path front for this node. */
AccessPathFrontNil getApf() { result = TFrontNil(this.getErasedReprType()) }
@@ -1337,7 +1339,7 @@ private class AccessPathNilNode extends Node {
AccessPathNilNode() { flowCand(this.(AccessPathFrontNilNode), _, _, _) }
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path for this node. */
AccessPathNil getAp() { result = TNil(this.getErasedReprType()) }
@@ -2076,7 +2078,7 @@ private module FlowExploration {
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
config.isSource(node) and
cc instanceof CallContextAny and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2091,7 +2093,9 @@ private module FlowExploration {
exists(PartialPathNode mid |
partialPathStep(mid, node, cc, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), ap.getType())
else any()
)
}
@@ -2194,7 +2198,7 @@ private module FlowExploration {
additionalLocalFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
)
or
@@ -2206,7 +2210,7 @@ private module FlowExploration {
additionalJumpStep(mid.getNode(), node, config) and
cc instanceof CallContextAny and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and

View File

@@ -464,7 +464,7 @@ private predicate simpleParameterFlow(
) {
throughFlowNodeCand(node, config) and
p = node and
t = getErasedRepr(node.getType()) and
t = getErasedNodeType(node) and
exists(ReturnNode ret, ReturnKind kind |
returnNodeGetEnclosingCallable(ret) = p.getEnclosingCallable() and
kind = ret.getKind() and
@@ -475,21 +475,21 @@ private predicate simpleParameterFlow(
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localFlowStep(mid, node, config) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, _, config) and
additionalLocalFlowStep(mid, node, config) and
t = getErasedRepr(node.getType())
t = getErasedNodeType(node)
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localStoreReadStep(mid, node) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// value flow through a callable
@@ -497,7 +497,7 @@ private predicate simpleParameterFlow(
exists(Node arg |
simpleParameterFlow(p, arg, t, config) and
argumentValueFlowsThrough(arg, node, _) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// flow through a callable
@@ -989,7 +989,9 @@ private class CastingNode extends Node {
*/
private predicate flowCandFwd(Node node, boolean fromArg, AccessPathFront apf, Configuration config) {
flowCandFwd0(node, fromArg, apf, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), apf.getType())
else any()
}
/**
@@ -1010,7 +1012,7 @@ private class AccessPathFrontNilNode extends Node {
}
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path front for this node. */
AccessPathFrontNil getApf() { result = TFrontNil(this.getErasedReprType()) }
@@ -1337,7 +1339,7 @@ private class AccessPathNilNode extends Node {
AccessPathNilNode() { flowCand(this.(AccessPathFrontNilNode), _, _, _) }
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path for this node. */
AccessPathNil getAp() { result = TNil(this.getErasedReprType()) }
@@ -2076,7 +2078,7 @@ private module FlowExploration {
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
config.isSource(node) and
cc instanceof CallContextAny and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2091,7 +2093,9 @@ private module FlowExploration {
exists(PartialPathNode mid |
partialPathStep(mid, node, cc, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), ap.getType())
else any()
)
}
@@ -2194,7 +2198,7 @@ private module FlowExploration {
additionalLocalFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
)
or
@@ -2206,7 +2210,7 @@ private module FlowExploration {
additionalJumpStep(mid.getNode(), node, config) and
cc instanceof CallContextAny and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and

View File

@@ -464,7 +464,7 @@ private predicate simpleParameterFlow(
) {
throughFlowNodeCand(node, config) and
p = node and
t = getErasedRepr(node.getType()) and
t = getErasedNodeType(node) and
exists(ReturnNode ret, ReturnKind kind |
returnNodeGetEnclosingCallable(ret) = p.getEnclosingCallable() and
kind = ret.getKind() and
@@ -475,21 +475,21 @@ private predicate simpleParameterFlow(
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localFlowStep(mid, node, config) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, _, config) and
additionalLocalFlowStep(mid, node, config) and
t = getErasedRepr(node.getType())
t = getErasedNodeType(node)
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localStoreReadStep(mid, node) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// value flow through a callable
@@ -497,7 +497,7 @@ private predicate simpleParameterFlow(
exists(Node arg |
simpleParameterFlow(p, arg, t, config) and
argumentValueFlowsThrough(arg, node, _) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// flow through a callable
@@ -989,7 +989,9 @@ private class CastingNode extends Node {
*/
private predicate flowCandFwd(Node node, boolean fromArg, AccessPathFront apf, Configuration config) {
flowCandFwd0(node, fromArg, apf, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), apf.getType())
else any()
}
/**
@@ -1010,7 +1012,7 @@ private class AccessPathFrontNilNode extends Node {
}
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path front for this node. */
AccessPathFrontNil getApf() { result = TFrontNil(this.getErasedReprType()) }
@@ -1337,7 +1339,7 @@ private class AccessPathNilNode extends Node {
AccessPathNilNode() { flowCand(this.(AccessPathFrontNilNode), _, _, _) }
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path for this node. */
AccessPathNil getAp() { result = TNil(this.getErasedReprType()) }
@@ -2076,7 +2078,7 @@ private module FlowExploration {
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
config.isSource(node) and
cc instanceof CallContextAny and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2091,7 +2093,9 @@ private module FlowExploration {
exists(PartialPathNode mid |
partialPathStep(mid, node, cc, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), ap.getType())
else any()
)
}
@@ -2194,7 +2198,7 @@ private module FlowExploration {
additionalLocalFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
)
or
@@ -2206,7 +2210,7 @@ private module FlowExploration {
additionalJumpStep(mid.getNode(), node, config) and
cc instanceof CallContextAny and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and

View File

@@ -464,7 +464,7 @@ private predicate simpleParameterFlow(
) {
throughFlowNodeCand(node, config) and
p = node and
t = getErasedRepr(node.getType()) and
t = getErasedNodeType(node) and
exists(ReturnNode ret, ReturnKind kind |
returnNodeGetEnclosingCallable(ret) = p.getEnclosingCallable() and
kind = ret.getKind() and
@@ -475,21 +475,21 @@ private predicate simpleParameterFlow(
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localFlowStep(mid, node, config) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, _, config) and
additionalLocalFlowStep(mid, node, config) and
t = getErasedRepr(node.getType())
t = getErasedNodeType(node)
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localStoreReadStep(mid, node) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// value flow through a callable
@@ -497,7 +497,7 @@ private predicate simpleParameterFlow(
exists(Node arg |
simpleParameterFlow(p, arg, t, config) and
argumentValueFlowsThrough(arg, node, _) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// flow through a callable
@@ -989,7 +989,9 @@ private class CastingNode extends Node {
*/
private predicate flowCandFwd(Node node, boolean fromArg, AccessPathFront apf, Configuration config) {
flowCandFwd0(node, fromArg, apf, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), apf.getType())
else any()
}
/**
@@ -1010,7 +1012,7 @@ private class AccessPathFrontNilNode extends Node {
}
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path front for this node. */
AccessPathFrontNil getApf() { result = TFrontNil(this.getErasedReprType()) }
@@ -1337,7 +1339,7 @@ private class AccessPathNilNode extends Node {
AccessPathNilNode() { flowCand(this.(AccessPathFrontNilNode), _, _, _) }
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path for this node. */
AccessPathNil getAp() { result = TNil(this.getErasedReprType()) }
@@ -2076,7 +2078,7 @@ private module FlowExploration {
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
config.isSource(node) and
cc instanceof CallContextAny and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2091,7 +2093,9 @@ private module FlowExploration {
exists(PartialPathNode mid |
partialPathStep(mid, node, cc, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), ap.getType())
else any()
)
}
@@ -2194,7 +2198,7 @@ private module FlowExploration {
additionalLocalFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
)
or
@@ -2206,7 +2210,7 @@ private module FlowExploration {
additionalJumpStep(mid.getNode(), node, config) and
cc instanceof CallContextAny and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and

View File

@@ -57,14 +57,14 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlowCand(p, mid) and
step(mid, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
or
// flow through a callable
exists(Node arg |
parameterValueFlowCand(p, arg) and
argumentValueFlowsThroughCand(arg, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
}
@@ -95,7 +95,7 @@ private module ImplCommon {
argumentValueFlowsThroughCand0(call, arg, kind)
|
out = getAnOutNode(call, kind) and
compatibleTypes(arg.getType(), out.getType())
compatibleTypes(getErasedNodeType(arg), getErasedNodeType(out))
)
}
@@ -183,7 +183,7 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlow(p, mid, cc) and
step(mid, node) and
compatibleTypes(p.getType(), node.getType()) and
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node)) and
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall())
)
or
@@ -191,7 +191,7 @@ private module ImplCommon {
exists(Node arg |
parameterValueFlow(p, arg, cc) and
argumentValueFlowsThrough(arg, node, cc) and
compatibleTypes(p.getType(), node.getType()) and
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node)) and
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall())
)
}
@@ -226,7 +226,7 @@ private module ImplCommon {
|
out = getAnOutNode(call, kind) and
not isUnreachableInCall(out, cc.(CallContextSpecificCall).getCall()) and
compatibleTypes(arg.getType(), out.getType())
compatibleTypes(getErasedNodeType(arg), getErasedNodeType(out))
)
}
}
@@ -260,7 +260,7 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlowNoCtx(p, mid) and
localValueStep(mid, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
}
@@ -296,8 +296,8 @@ private module ImplCommon {
setterCall(call, i1, i2, f) and
node1.(ArgumentNode).argumentOf(call, i1) and
node2.getPreUpdateNode().(ArgumentNode).argumentOf(call, i2) and
compatibleTypes(node1.getTypeBound(), f.getType()) and
compatibleTypes(node2.getTypeBound(), f.getContainerType())
compatibleTypes(getErasedNodeTypeBound(node1), f.getType()) and
compatibleTypes(getErasedNodeTypeBound(node2), f.getContainerType())
)
}
@@ -333,8 +333,8 @@ private module ImplCommon {
exists(DataFlowCall call, ReturnKind kind |
storeReturn0(call, kind, node1, f) and
node2 = getAnOutNode(call, kind) and
compatibleTypes(node1.getTypeBound(), f.getType()) and
compatibleTypes(node2.getTypeBound(), f.getContainerType())
compatibleTypes(getErasedNodeTypeBound(node1), f.getType()) and
compatibleTypes(getErasedNodeTypeBound(node2), f.getContainerType())
)
}
@@ -365,8 +365,8 @@ private module ImplCommon {
exists(DataFlowCall call, ReturnKind kind |
read0(call, kind, node1, f) and
node2 = getAnOutNode(call, kind) and
compatibleTypes(node1.getTypeBound(), f.getContainerType()) and
compatibleTypes(node2.getTypeBound(), f.getType())
compatibleTypes(getErasedNodeTypeBound(node1), f.getContainerType()) and
compatibleTypes(getErasedNodeTypeBound(node2), f.getType())
)
}
@@ -384,7 +384,7 @@ private module ImplCommon {
store(node1, f, mid1) and
localValueStep*(mid1, mid2) and
read(mid2, f, node2) and
compatibleTypes(node1.getTypeBound(), node2.getTypeBound())
compatibleTypes(getErasedNodeTypeBound(node1), getErasedNodeTypeBound(node2))
)
}
@@ -405,14 +405,14 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlowCand(p, mid) and
step(mid, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
or
// flow through a callable
exists(Node arg |
parameterValueFlowCand(p, arg) and
argumentValueFlowsThroughCand(arg, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
}
@@ -443,7 +443,7 @@ private module ImplCommon {
argumentValueFlowsThroughCand0(call, arg, kind)
|
out = getAnOutNode(call, kind) and
compatibleTypes(arg.getType(), out.getType())
compatibleTypes(getErasedNodeType(arg), getErasedNodeType(out))
)
}
@@ -531,7 +531,7 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlow(p, mid, cc) and
step(mid, node) and
compatibleTypes(p.getType(), node.getType()) and
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node)) and
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall())
)
or
@@ -539,7 +539,7 @@ private module ImplCommon {
exists(Node arg |
parameterValueFlow(p, arg, cc) and
argumentValueFlowsThrough(arg, node, cc) and
compatibleTypes(p.getType(), node.getType()) and
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node)) and
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall())
)
}
@@ -574,7 +574,7 @@ private module ImplCommon {
|
out = getAnOutNode(call, kind) and
not isUnreachableInCall(out, cc.(CallContextSpecificCall).getCall()) and
compatibleTypes(arg.getType(), out.getType())
compatibleTypes(getErasedNodeType(arg), getErasedNodeType(out))
)
}
}
@@ -860,4 +860,10 @@ private module ImplCommon {
or
result = viableCallable(call) and cc instanceof CallContextReturn
}
pragma[noinline]
DataFlowType getErasedNodeType(Node n) { result = getErasedRepr(n.getType()) }
pragma[noinline]
DataFlowType getErasedNodeTypeBound(Node n) { result = getErasedRepr(n.getTypeBound()) }
}

View File

@@ -464,7 +464,7 @@ private predicate simpleParameterFlow(
) {
throughFlowNodeCand(node, config) and
p = node and
t = getErasedRepr(node.getType()) and
t = getErasedNodeType(node) and
exists(ReturnNode ret, ReturnKind kind |
returnNodeGetEnclosingCallable(ret) = p.getEnclosingCallable() and
kind = ret.getKind() and
@@ -475,21 +475,21 @@ private predicate simpleParameterFlow(
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localFlowStep(mid, node, config) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, _, config) and
additionalLocalFlowStep(mid, node, config) and
t = getErasedRepr(node.getType())
t = getErasedNodeType(node)
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localStoreReadStep(mid, node) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// value flow through a callable
@@ -497,7 +497,7 @@ private predicate simpleParameterFlow(
exists(Node arg |
simpleParameterFlow(p, arg, t, config) and
argumentValueFlowsThrough(arg, node, _) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// flow through a callable
@@ -989,7 +989,9 @@ private class CastingNode extends Node {
*/
private predicate flowCandFwd(Node node, boolean fromArg, AccessPathFront apf, Configuration config) {
flowCandFwd0(node, fromArg, apf, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), apf.getType())
else any()
}
/**
@@ -1010,7 +1012,7 @@ private class AccessPathFrontNilNode extends Node {
}
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path front for this node. */
AccessPathFrontNil getApf() { result = TFrontNil(this.getErasedReprType()) }
@@ -1337,7 +1339,7 @@ private class AccessPathNilNode extends Node {
AccessPathNilNode() { flowCand(this.(AccessPathFrontNilNode), _, _, _) }
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path for this node. */
AccessPathNil getAp() { result = TNil(this.getErasedReprType()) }
@@ -2076,7 +2078,7 @@ private module FlowExploration {
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
config.isSource(node) and
cc instanceof CallContextAny and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2091,7 +2093,9 @@ private module FlowExploration {
exists(PartialPathNode mid |
partialPathStep(mid, node, cc, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), ap.getType())
else any()
)
}
@@ -2194,7 +2198,7 @@ private module FlowExploration {
additionalLocalFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
)
or
@@ -2206,7 +2210,7 @@ private module FlowExploration {
additionalJumpStep(mid.getNode(), node, config) and
cc instanceof CallContextAny and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and

View File

@@ -219,7 +219,6 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
node1.asExpr() = a and
a.getLValue() = fa
) and
not fa.getTarget().isStatic() and
node2.getPreUpdateNode().asExpr() = fa.getQualifier() and
f.(FieldContent).getField() = fa.getTarget()
)

View File

@@ -182,7 +182,7 @@ class ImplicitParameterNode extends ParameterNode, TInstanceParameterNode {
override Type getType() { result = f.getDeclaringType() }
override string toString() { result = "`this` parameter in " + f.getName() }
override string toString() { result = "this" }
override Location getLocation() { result = f.getLocation() }

View File

@@ -133,8 +133,7 @@ private module PartialDefinitions {
TReferenceArgument(Expr arg, VariableAccess va) { referenceArgument(va, arg) }
private predicate isInstanceFieldWrite(FieldAccess fa, ControlFlowNode node) {
not fa.getTarget().isStatic() and
assignmentLikeOperation(node, fa.getTarget(), fa, _)
assignmentLikeOperation(node, _, fa, _)
}
class PartialDefinition extends TPartialDefinition {

View File

@@ -464,7 +464,7 @@ private predicate simpleParameterFlow(
) {
throughFlowNodeCand(node, config) and
p = node and
t = getErasedRepr(node.getType()) and
t = getErasedNodeType(node) and
exists(ReturnNode ret, ReturnKind kind |
returnNodeGetEnclosingCallable(ret) = p.getEnclosingCallable() and
kind = ret.getKind() and
@@ -475,21 +475,21 @@ private predicate simpleParameterFlow(
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localFlowStep(mid, node, config) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, _, config) and
additionalLocalFlowStep(mid, node, config) and
t = getErasedRepr(node.getType())
t = getErasedNodeType(node)
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localStoreReadStep(mid, node) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// value flow through a callable
@@ -497,7 +497,7 @@ private predicate simpleParameterFlow(
exists(Node arg |
simpleParameterFlow(p, arg, t, config) and
argumentValueFlowsThrough(arg, node, _) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// flow through a callable
@@ -989,7 +989,9 @@ private class CastingNode extends Node {
*/
private predicate flowCandFwd(Node node, boolean fromArg, AccessPathFront apf, Configuration config) {
flowCandFwd0(node, fromArg, apf, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), apf.getType())
else any()
}
/**
@@ -1010,7 +1012,7 @@ private class AccessPathFrontNilNode extends Node {
}
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path front for this node. */
AccessPathFrontNil getApf() { result = TFrontNil(this.getErasedReprType()) }
@@ -1337,7 +1339,7 @@ private class AccessPathNilNode extends Node {
AccessPathNilNode() { flowCand(this.(AccessPathFrontNilNode), _, _, _) }
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path for this node. */
AccessPathNil getAp() { result = TNil(this.getErasedReprType()) }
@@ -2076,7 +2078,7 @@ private module FlowExploration {
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
config.isSource(node) and
cc instanceof CallContextAny and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2091,7 +2093,9 @@ private module FlowExploration {
exists(PartialPathNode mid |
partialPathStep(mid, node, cc, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), ap.getType())
else any()
)
}
@@ -2194,7 +2198,7 @@ private module FlowExploration {
additionalLocalFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
)
or
@@ -2206,7 +2210,7 @@ private module FlowExploration {
additionalJumpStep(mid.getNode(), node, config) and
cc instanceof CallContextAny and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and

View File

@@ -464,7 +464,7 @@ private predicate simpleParameterFlow(
) {
throughFlowNodeCand(node, config) and
p = node and
t = getErasedRepr(node.getType()) and
t = getErasedNodeType(node) and
exists(ReturnNode ret, ReturnKind kind |
returnNodeGetEnclosingCallable(ret) = p.getEnclosingCallable() and
kind = ret.getKind() and
@@ -475,21 +475,21 @@ private predicate simpleParameterFlow(
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localFlowStep(mid, node, config) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, _, config) and
additionalLocalFlowStep(mid, node, config) and
t = getErasedRepr(node.getType())
t = getErasedNodeType(node)
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localStoreReadStep(mid, node) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// value flow through a callable
@@ -497,7 +497,7 @@ private predicate simpleParameterFlow(
exists(Node arg |
simpleParameterFlow(p, arg, t, config) and
argumentValueFlowsThrough(arg, node, _) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// flow through a callable
@@ -989,7 +989,9 @@ private class CastingNode extends Node {
*/
private predicate flowCandFwd(Node node, boolean fromArg, AccessPathFront apf, Configuration config) {
flowCandFwd0(node, fromArg, apf, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), apf.getType())
else any()
}
/**
@@ -1010,7 +1012,7 @@ private class AccessPathFrontNilNode extends Node {
}
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path front for this node. */
AccessPathFrontNil getApf() { result = TFrontNil(this.getErasedReprType()) }
@@ -1337,7 +1339,7 @@ private class AccessPathNilNode extends Node {
AccessPathNilNode() { flowCand(this.(AccessPathFrontNilNode), _, _, _) }
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path for this node. */
AccessPathNil getAp() { result = TNil(this.getErasedReprType()) }
@@ -2076,7 +2078,7 @@ private module FlowExploration {
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
config.isSource(node) and
cc instanceof CallContextAny and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2091,7 +2093,9 @@ private module FlowExploration {
exists(PartialPathNode mid |
partialPathStep(mid, node, cc, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), ap.getType())
else any()
)
}
@@ -2194,7 +2198,7 @@ private module FlowExploration {
additionalLocalFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
)
or
@@ -2206,7 +2210,7 @@ private module FlowExploration {
additionalJumpStep(mid.getNode(), node, config) and
cc instanceof CallContextAny and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and

View File

@@ -464,7 +464,7 @@ private predicate simpleParameterFlow(
) {
throughFlowNodeCand(node, config) and
p = node and
t = getErasedRepr(node.getType()) and
t = getErasedNodeType(node) and
exists(ReturnNode ret, ReturnKind kind |
returnNodeGetEnclosingCallable(ret) = p.getEnclosingCallable() and
kind = ret.getKind() and
@@ -475,21 +475,21 @@ private predicate simpleParameterFlow(
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localFlowStep(mid, node, config) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, _, config) and
additionalLocalFlowStep(mid, node, config) and
t = getErasedRepr(node.getType())
t = getErasedNodeType(node)
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localStoreReadStep(mid, node) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// value flow through a callable
@@ -497,7 +497,7 @@ private predicate simpleParameterFlow(
exists(Node arg |
simpleParameterFlow(p, arg, t, config) and
argumentValueFlowsThrough(arg, node, _) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// flow through a callable
@@ -989,7 +989,9 @@ private class CastingNode extends Node {
*/
private predicate flowCandFwd(Node node, boolean fromArg, AccessPathFront apf, Configuration config) {
flowCandFwd0(node, fromArg, apf, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), apf.getType())
else any()
}
/**
@@ -1010,7 +1012,7 @@ private class AccessPathFrontNilNode extends Node {
}
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path front for this node. */
AccessPathFrontNil getApf() { result = TFrontNil(this.getErasedReprType()) }
@@ -1337,7 +1339,7 @@ private class AccessPathNilNode extends Node {
AccessPathNilNode() { flowCand(this.(AccessPathFrontNilNode), _, _, _) }
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path for this node. */
AccessPathNil getAp() { result = TNil(this.getErasedReprType()) }
@@ -2076,7 +2078,7 @@ private module FlowExploration {
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
config.isSource(node) and
cc instanceof CallContextAny and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2091,7 +2093,9 @@ private module FlowExploration {
exists(PartialPathNode mid |
partialPathStep(mid, node, cc, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), ap.getType())
else any()
)
}
@@ -2194,7 +2198,7 @@ private module FlowExploration {
additionalLocalFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
)
or
@@ -2206,7 +2210,7 @@ private module FlowExploration {
additionalJumpStep(mid.getNode(), node, config) and
cc instanceof CallContextAny and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and

View File

@@ -464,7 +464,7 @@ private predicate simpleParameterFlow(
) {
throughFlowNodeCand(node, config) and
p = node and
t = getErasedRepr(node.getType()) and
t = getErasedNodeType(node) and
exists(ReturnNode ret, ReturnKind kind |
returnNodeGetEnclosingCallable(ret) = p.getEnclosingCallable() and
kind = ret.getKind() and
@@ -475,21 +475,21 @@ private predicate simpleParameterFlow(
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localFlowStep(mid, node, config) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, _, config) and
additionalLocalFlowStep(mid, node, config) and
t = getErasedRepr(node.getType())
t = getErasedNodeType(node)
)
or
throughFlowNodeCand(node, unbind(config)) and
exists(Node mid |
simpleParameterFlow(p, mid, t, config) and
localStoreReadStep(mid, node) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// value flow through a callable
@@ -497,7 +497,7 @@ private predicate simpleParameterFlow(
exists(Node arg |
simpleParameterFlow(p, arg, t, config) and
argumentValueFlowsThrough(arg, node, _) and
compatibleTypes(t, node.getType())
compatibleTypes(t, getErasedNodeType(node))
)
or
// flow through a callable
@@ -989,7 +989,9 @@ private class CastingNode extends Node {
*/
private predicate flowCandFwd(Node node, boolean fromArg, AccessPathFront apf, Configuration config) {
flowCandFwd0(node, fromArg, apf, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), apf.getType())
else any()
}
/**
@@ -1010,7 +1012,7 @@ private class AccessPathFrontNilNode extends Node {
}
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path front for this node. */
AccessPathFrontNil getApf() { result = TFrontNil(this.getErasedReprType()) }
@@ -1337,7 +1339,7 @@ private class AccessPathNilNode extends Node {
AccessPathNilNode() { flowCand(this.(AccessPathFrontNilNode), _, _, _) }
pragma[noinline]
private DataFlowType getErasedReprType() { result = getErasedRepr(this.getType()) }
private DataFlowType getErasedReprType() { result = getErasedNodeType(this) }
/** Gets the `nil` path for this node. */
AccessPathNil getAp() { result = TNil(this.getErasedReprType()) }
@@ -2076,7 +2078,7 @@ private module FlowExploration {
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
config.isSource(node) and
cc instanceof CallContextAny and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2091,7 +2093,9 @@ private module FlowExploration {
exists(PartialPathNode mid |
partialPathStep(mid, node, cc, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode then compatibleTypes(node.getType(), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeType(node), ap.getType())
else any()
)
}
@@ -2194,7 +2198,7 @@ private module FlowExploration {
additionalLocalFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
)
or
@@ -2206,7 +2210,7 @@ private module FlowExploration {
additionalJumpStep(mid.getNode(), node, config) and
cc instanceof CallContextAny and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getErasedRepr(node.getType())) and
ap = TPartialNil(getErasedNodeType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and

View File

@@ -57,14 +57,14 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlowCand(p, mid) and
step(mid, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
or
// flow through a callable
exists(Node arg |
parameterValueFlowCand(p, arg) and
argumentValueFlowsThroughCand(arg, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
}
@@ -95,7 +95,7 @@ private module ImplCommon {
argumentValueFlowsThroughCand0(call, arg, kind)
|
out = getAnOutNode(call, kind) and
compatibleTypes(arg.getType(), out.getType())
compatibleTypes(getErasedNodeType(arg), getErasedNodeType(out))
)
}
@@ -183,7 +183,7 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlow(p, mid, cc) and
step(mid, node) and
compatibleTypes(p.getType(), node.getType()) and
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node)) and
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall())
)
or
@@ -191,7 +191,7 @@ private module ImplCommon {
exists(Node arg |
parameterValueFlow(p, arg, cc) and
argumentValueFlowsThrough(arg, node, cc) and
compatibleTypes(p.getType(), node.getType()) and
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node)) and
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall())
)
}
@@ -226,7 +226,7 @@ private module ImplCommon {
|
out = getAnOutNode(call, kind) and
not isUnreachableInCall(out, cc.(CallContextSpecificCall).getCall()) and
compatibleTypes(arg.getType(), out.getType())
compatibleTypes(getErasedNodeType(arg), getErasedNodeType(out))
)
}
}
@@ -260,7 +260,7 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlowNoCtx(p, mid) and
localValueStep(mid, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
}
@@ -296,8 +296,8 @@ private module ImplCommon {
setterCall(call, i1, i2, f) and
node1.(ArgumentNode).argumentOf(call, i1) and
node2.getPreUpdateNode().(ArgumentNode).argumentOf(call, i2) and
compatibleTypes(node1.getTypeBound(), f.getType()) and
compatibleTypes(node2.getTypeBound(), f.getContainerType())
compatibleTypes(getErasedNodeTypeBound(node1), f.getType()) and
compatibleTypes(getErasedNodeTypeBound(node2), f.getContainerType())
)
}
@@ -333,8 +333,8 @@ private module ImplCommon {
exists(DataFlowCall call, ReturnKind kind |
storeReturn0(call, kind, node1, f) and
node2 = getAnOutNode(call, kind) and
compatibleTypes(node1.getTypeBound(), f.getType()) and
compatibleTypes(node2.getTypeBound(), f.getContainerType())
compatibleTypes(getErasedNodeTypeBound(node1), f.getType()) and
compatibleTypes(getErasedNodeTypeBound(node2), f.getContainerType())
)
}
@@ -365,8 +365,8 @@ private module ImplCommon {
exists(DataFlowCall call, ReturnKind kind |
read0(call, kind, node1, f) and
node2 = getAnOutNode(call, kind) and
compatibleTypes(node1.getTypeBound(), f.getContainerType()) and
compatibleTypes(node2.getTypeBound(), f.getType())
compatibleTypes(getErasedNodeTypeBound(node1), f.getContainerType()) and
compatibleTypes(getErasedNodeTypeBound(node2), f.getType())
)
}
@@ -384,7 +384,7 @@ private module ImplCommon {
store(node1, f, mid1) and
localValueStep*(mid1, mid2) and
read(mid2, f, node2) and
compatibleTypes(node1.getTypeBound(), node2.getTypeBound())
compatibleTypes(getErasedNodeTypeBound(node1), getErasedNodeTypeBound(node2))
)
}
@@ -405,14 +405,14 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlowCand(p, mid) and
step(mid, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
or
// flow through a callable
exists(Node arg |
parameterValueFlowCand(p, arg) and
argumentValueFlowsThroughCand(arg, node) and
compatibleTypes(p.getType(), node.getType())
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node))
)
}
@@ -443,7 +443,7 @@ private module ImplCommon {
argumentValueFlowsThroughCand0(call, arg, kind)
|
out = getAnOutNode(call, kind) and
compatibleTypes(arg.getType(), out.getType())
compatibleTypes(getErasedNodeType(arg), getErasedNodeType(out))
)
}
@@ -531,7 +531,7 @@ private module ImplCommon {
exists(Node mid |
parameterValueFlow(p, mid, cc) and
step(mid, node) and
compatibleTypes(p.getType(), node.getType()) and
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node)) and
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall())
)
or
@@ -539,7 +539,7 @@ private module ImplCommon {
exists(Node arg |
parameterValueFlow(p, arg, cc) and
argumentValueFlowsThrough(arg, node, cc) and
compatibleTypes(p.getType(), node.getType()) and
compatibleTypes(getErasedNodeType(p), getErasedNodeType(node)) and
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall())
)
}
@@ -574,7 +574,7 @@ private module ImplCommon {
|
out = getAnOutNode(call, kind) and
not isUnreachableInCall(out, cc.(CallContextSpecificCall).getCall()) and
compatibleTypes(arg.getType(), out.getType())
compatibleTypes(getErasedNodeType(arg), getErasedNodeType(out))
)
}
}
@@ -860,4 +860,10 @@ private module ImplCommon {
or
result = viableCallable(call) and cc instanceof CallContextReturn
}
pragma[noinline]
DataFlowType getErasedNodeType(Node n) { result = getErasedRepr(n.getType()) }
pragma[noinline]
DataFlowType getErasedNodeTypeBound(Node n) { result = getErasedRepr(n.getTypeBound()) }
}

View File

@@ -85,7 +85,11 @@ class Node extends TIRDataFlowNode {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
string toString() { result = instr.toString() }
string toString() {
// This predicate is overridden in subclasses. This default implementation
// does not use `Instruction.toString` because that's expensive to compute.
result = this.asInstruction().getOpcode().toString()
}
}
/**
@@ -107,6 +111,8 @@ class ExprNode extends Node {
* expression may be a `Conversion`.
*/
Expr getConvertedExpr() { result = this.asConvertedExpr() }
override string toString() { result = this.asConvertedExpr().toString() }
}
/**
@@ -123,6 +129,14 @@ class ParameterNode extends Node {
predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() }
Parameter getParameter() { result = instr.getParameter() }
override string toString() { result = instr.getParameter().toString() }
}
private class ThisParameterNode extends Node {
override InitializeThisInstruction instr;
override string toString() { result = "this" }
}
/**
@@ -133,6 +147,8 @@ class UninitializedNode extends Node {
override UninitializedInstruction instr;
LocalVariable getLocalVariable() { result = instr.getLocalVariable() }
override string toString() { result = this.getLocalVariable().toString() }
}
/**

View File

@@ -13,14 +13,20 @@ IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var
}
/**
* Represents a variable referenced by the IR for a function. The variable may
* be a user-declared variable (`IRUserVariable`) or a temporary variable
* generated by the AST-to-IR translation (`IRTempVariable`).
* A variable referenced by the IR for a function. The variable may be a user-declared variable
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
* (`IRTempVariable`).
*/
abstract class IRVariable extends TIRVariable {
class IRVariable extends TIRVariable {
Language::Function func;
abstract string toString();
IRVariable() {
this = TIRUserVariable(_, _, func) or
this = TIRTempVariable(func, _, _, _) or
this = TIRStringLiteral(func, _, _, _)
}
string toString() { none() }
/**
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -41,19 +47,19 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the type of the variable.
*/
abstract Language::LanguageType getLanguageType();
Language::LanguageType getLanguageType() { none() }
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
abstract Language::AST getAST();
Language::AST getAST() { none() }
/**
* Gets an identifier string for the variable. This identifier is unique
* within the function.
*/
abstract string getUniqueId();
string getUniqueId() { none() }
/**
* Gets the source location of this variable.
@@ -72,7 +78,7 @@ abstract class IRVariable extends TIRVariable {
}
/**
* Represents a user-declared variable referenced by the IR for a function.
* A user-declared variable referenced by the IR for a function.
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
@@ -97,20 +103,34 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
}
/**
* Represents a variable (user-declared or temporary) that is allocated on the
* stack. This includes all parameters, non-static local variables, and
* temporary variables.
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
abstract class IRAutomaticVariable extends IRVariable { }
class IRAutomaticVariable extends IRVariable {
IRAutomaticVariable() {
exists(Language::Variable var |
this = TIRUserVariable(var, _, func) and
Language::isVariableAutomatic(var)
)
or
this = TIRTempVariable(func, _, _, _)
}
}
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
final override Language::AutomaticVariable getVariable() { result = var }
}
/**
* A user-declared variable that is not allocated on the stack. This includes all global variables,
* namespace-scope variables, static fields, and static local variables.
*/
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
@@ -119,10 +139,19 @@ class IRStaticUserVariable extends IRUserVariable {
final override Language::StaticVariable getVariable() { result = var }
}
abstract class IRGeneratedVariable extends IRVariable {
/**
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
class IRGeneratedVariable extends IRVariable {
Language::AST ast;
Language::LanguageType type;
IRGeneratedVariable() {
this = TIRTempVariable(func, ast, _, type) or
this = TIRStringLiteral(func, ast, type, _)
}
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAST() { result = ast }
@@ -144,6 +173,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
result.getTag() = tag
}
/**
* A temporary variable introduced by IR construction. The most common examples are the variable
* generated to hold the return value of afunction, or the variable generated to hold the result of
* a condition operator (`a ? b : c`).
*/
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
TempVariableTag tag;
@@ -158,18 +192,28 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
override string getBaseString() { result = "#temp" }
}
/**
* A temporary variable generated to hold the return value of a function.
*/
class IRReturnVariable extends IRTempVariable {
IRReturnVariable() { tag = ReturnValueTempVar() }
final override string toString() { result = "#return" }
}
/**
* A temporary variable generated to hold the exception thrown by a `ThrowValue` instruction.
*/
class IRThrowVariable extends IRTempVariable {
IRThrowVariable() { tag = ThrowTempVar() }
override string getBaseString() { result = "#throw" }
}
/**
* A variable generated to represent the contents of a string literal. This variable acts much like
* a read-only global variable.
*/
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
Language::StringLiteral literal;

View File

@@ -94,12 +94,21 @@ module InstructionSanity {
/**
* Holds if instruction `instr` has multiple operands with tag `tag`.
*/
query predicate duplicateOperand(Instruction instr, OperandTag tag) {
strictcount(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
) > 1 and
not tag instanceof UnmodeledUseOperandTag
query predicate duplicateOperand(
Instruction instr, string message, IRFunction func, string funcText
) {
exists(OperandTag tag, int operandCount |
operandCount = strictcount(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
) and
operandCount > 1 and
not tag instanceof UnmodeledUseOperandTag and
message = "Instruction has " + operandCount + " operands with tag '" + tag.toString() + "'" +
" in function '$@'." and
func = instr.getEnclosingIRFunction() and
funcText = Language::getIdentityString(func.getFunction())
)
}
/**

View File

@@ -6,26 +6,6 @@ private import semmle.code.cpp.models.interfaces.Alias
private class IntValue = Ints::IntValue;
/**
* Converts the bit count in `bits` to a byte count and a bit count in the form
* bytes:bits.
*/
bindingset[bits]
string bitsToBytesAndBits(int bits) { result = (bits / 8).toString() + ":" + (bits % 8).toString() }
/**
* Gets a printable string for a bit offset with possibly unknown value.
*/
bindingset[bitOffset]
string getBitOffsetString(IntValue bitOffset) {
if Ints::hasValue(bitOffset)
then
if bitOffset >= 0
then result = "+" + bitsToBytesAndBits(bitOffset)
else result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset))
else result = "+?"
}
/**
* Gets the offset of field `field` in bits.
*/
@@ -137,7 +117,11 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
or
// Adding an integer to or subtracting an integer from a pointer propagates
// the address with an offset.
bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction))
exists(PointerOffsetInstruction ptrOffset |
ptrOffset = instr and
operand = ptrOffset.getLeftOperand() and
bitOffset = getPointerBitOffset(ptrOffset)
)
or
// Computing a field address from a pointer propagates the address plus the
// offset of the field.

View File

@@ -865,3 +865,17 @@ private module CachedForDebugging {
result.getTag() = var.getTag()
}
}
module SSASanity {
query predicate multipleOperandMemoryLocations(
OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText
) {
exists(int locationCount |
locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and
locationCount > 1 and
func = operand.getEnclosingIRFunction() and
funcText = Language::getIdentityString(func.getFunction()) and
message = "Operand has " + locationCount.toString() + " memory accesses in function '$@'."
)
}
}

View File

@@ -0,0 +1,8 @@
/**
* @name Aliased SSA Sanity Check
* @description Performs sanity checks on the SSA construction. This query should have no results.
* @kind table
* @id cpp/aliased-ssa-sanity-check
*/
import SSASanity

View File

@@ -0,0 +1,2 @@
private import SSAConstruction as SSA
import SSA::SSASanity

View File

@@ -13,14 +13,20 @@ IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var
}
/**
* Represents a variable referenced by the IR for a function. The variable may
* be a user-declared variable (`IRUserVariable`) or a temporary variable
* generated by the AST-to-IR translation (`IRTempVariable`).
* A variable referenced by the IR for a function. The variable may be a user-declared variable
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
* (`IRTempVariable`).
*/
abstract class IRVariable extends TIRVariable {
class IRVariable extends TIRVariable {
Language::Function func;
abstract string toString();
IRVariable() {
this = TIRUserVariable(_, _, func) or
this = TIRTempVariable(func, _, _, _) or
this = TIRStringLiteral(func, _, _, _)
}
string toString() { none() }
/**
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -41,19 +47,19 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the type of the variable.
*/
abstract Language::LanguageType getLanguageType();
Language::LanguageType getLanguageType() { none() }
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
abstract Language::AST getAST();
Language::AST getAST() { none() }
/**
* Gets an identifier string for the variable. This identifier is unique
* within the function.
*/
abstract string getUniqueId();
string getUniqueId() { none() }
/**
* Gets the source location of this variable.
@@ -72,7 +78,7 @@ abstract class IRVariable extends TIRVariable {
}
/**
* Represents a user-declared variable referenced by the IR for a function.
* A user-declared variable referenced by the IR for a function.
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
@@ -97,20 +103,34 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
}
/**
* Represents a variable (user-declared or temporary) that is allocated on the
* stack. This includes all parameters, non-static local variables, and
* temporary variables.
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
abstract class IRAutomaticVariable extends IRVariable { }
class IRAutomaticVariable extends IRVariable {
IRAutomaticVariable() {
exists(Language::Variable var |
this = TIRUserVariable(var, _, func) and
Language::isVariableAutomatic(var)
)
or
this = TIRTempVariable(func, _, _, _)
}
}
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
final override Language::AutomaticVariable getVariable() { result = var }
}
/**
* A user-declared variable that is not allocated on the stack. This includes all global variables,
* namespace-scope variables, static fields, and static local variables.
*/
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
@@ -119,10 +139,19 @@ class IRStaticUserVariable extends IRUserVariable {
final override Language::StaticVariable getVariable() { result = var }
}
abstract class IRGeneratedVariable extends IRVariable {
/**
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
class IRGeneratedVariable extends IRVariable {
Language::AST ast;
Language::LanguageType type;
IRGeneratedVariable() {
this = TIRTempVariable(func, ast, _, type) or
this = TIRStringLiteral(func, ast, type, _)
}
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAST() { result = ast }
@@ -144,6 +173,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
result.getTag() = tag
}
/**
* A temporary variable introduced by IR construction. The most common examples are the variable
* generated to hold the return value of afunction, or the variable generated to hold the result of
* a condition operator (`a ? b : c`).
*/
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
TempVariableTag tag;
@@ -158,18 +192,28 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
override string getBaseString() { result = "#temp" }
}
/**
* A temporary variable generated to hold the return value of a function.
*/
class IRReturnVariable extends IRTempVariable {
IRReturnVariable() { tag = ReturnValueTempVar() }
final override string toString() { result = "#return" }
}
/**
* A temporary variable generated to hold the exception thrown by a `ThrowValue` instruction.
*/
class IRThrowVariable extends IRTempVariable {
IRThrowVariable() { tag = ThrowTempVar() }
override string getBaseString() { result = "#throw" }
}
/**
* A variable generated to represent the contents of a string literal. This variable acts much like
* a read-only global variable.
*/
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
Language::StringLiteral literal;

View File

@@ -94,12 +94,21 @@ module InstructionSanity {
/**
* Holds if instruction `instr` has multiple operands with tag `tag`.
*/
query predicate duplicateOperand(Instruction instr, OperandTag tag) {
strictcount(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
) > 1 and
not tag instanceof UnmodeledUseOperandTag
query predicate duplicateOperand(
Instruction instr, string message, IRFunction func, string funcText
) {
exists(OperandTag tag, int operandCount |
operandCount = strictcount(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
) and
operandCount > 1 and
not tag instanceof UnmodeledUseOperandTag and
message = "Instruction has " + operandCount + " operands with tag '" + tag.toString() + "'" +
" in function '$@'." and
func = instr.getEnclosingIRFunction() and
funcText = Language::getIdentityString(func.getFunction())
)
}
/**

View File

@@ -13,14 +13,20 @@ IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var
}
/**
* Represents a variable referenced by the IR for a function. The variable may
* be a user-declared variable (`IRUserVariable`) or a temporary variable
* generated by the AST-to-IR translation (`IRTempVariable`).
* A variable referenced by the IR for a function. The variable may be a user-declared variable
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
* (`IRTempVariable`).
*/
abstract class IRVariable extends TIRVariable {
class IRVariable extends TIRVariable {
Language::Function func;
abstract string toString();
IRVariable() {
this = TIRUserVariable(_, _, func) or
this = TIRTempVariable(func, _, _, _) or
this = TIRStringLiteral(func, _, _, _)
}
string toString() { none() }
/**
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -41,19 +47,19 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the type of the variable.
*/
abstract Language::LanguageType getLanguageType();
Language::LanguageType getLanguageType() { none() }
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
abstract Language::AST getAST();
Language::AST getAST() { none() }
/**
* Gets an identifier string for the variable. This identifier is unique
* within the function.
*/
abstract string getUniqueId();
string getUniqueId() { none() }
/**
* Gets the source location of this variable.
@@ -72,7 +78,7 @@ abstract class IRVariable extends TIRVariable {
}
/**
* Represents a user-declared variable referenced by the IR for a function.
* A user-declared variable referenced by the IR for a function.
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
@@ -97,20 +103,34 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
}
/**
* Represents a variable (user-declared or temporary) that is allocated on the
* stack. This includes all parameters, non-static local variables, and
* temporary variables.
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
abstract class IRAutomaticVariable extends IRVariable { }
class IRAutomaticVariable extends IRVariable {
IRAutomaticVariable() {
exists(Language::Variable var |
this = TIRUserVariable(var, _, func) and
Language::isVariableAutomatic(var)
)
or
this = TIRTempVariable(func, _, _, _)
}
}
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
final override Language::AutomaticVariable getVariable() { result = var }
}
/**
* A user-declared variable that is not allocated on the stack. This includes all global variables,
* namespace-scope variables, static fields, and static local variables.
*/
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
@@ -119,10 +139,19 @@ class IRStaticUserVariable extends IRUserVariable {
final override Language::StaticVariable getVariable() { result = var }
}
abstract class IRGeneratedVariable extends IRVariable {
/**
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
class IRGeneratedVariable extends IRVariable {
Language::AST ast;
Language::LanguageType type;
IRGeneratedVariable() {
this = TIRTempVariable(func, ast, _, type) or
this = TIRStringLiteral(func, ast, type, _)
}
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAST() { result = ast }
@@ -144,6 +173,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
result.getTag() = tag
}
/**
* A temporary variable introduced by IR construction. The most common examples are the variable
* generated to hold the return value of afunction, or the variable generated to hold the result of
* a condition operator (`a ? b : c`).
*/
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
TempVariableTag tag;
@@ -158,18 +192,28 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
override string getBaseString() { result = "#temp" }
}
/**
* A temporary variable generated to hold the return value of a function.
*/
class IRReturnVariable extends IRTempVariable {
IRReturnVariable() { tag = ReturnValueTempVar() }
final override string toString() { result = "#return" }
}
/**
* A temporary variable generated to hold the exception thrown by a `ThrowValue` instruction.
*/
class IRThrowVariable extends IRTempVariable {
IRThrowVariable() { tag = ThrowTempVar() }
override string getBaseString() { result = "#throw" }
}
/**
* A variable generated to represent the contents of a string literal. This variable acts much like
* a read-only global variable.
*/
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
Language::StringLiteral literal;

View File

@@ -94,12 +94,21 @@ module InstructionSanity {
/**
* Holds if instruction `instr` has multiple operands with tag `tag`.
*/
query predicate duplicateOperand(Instruction instr, OperandTag tag) {
strictcount(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
) > 1 and
not tag instanceof UnmodeledUseOperandTag
query predicate duplicateOperand(
Instruction instr, string message, IRFunction func, string funcText
) {
exists(OperandTag tag, int operandCount |
operandCount = strictcount(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
) and
operandCount > 1 and
not tag instanceof UnmodeledUseOperandTag and
message = "Instruction has " + operandCount + " operands with tag '" + tag.toString() + "'" +
" in function '$@'." and
func = instr.getEnclosingIRFunction() and
funcText = Language::getIdentityString(func.getFunction())
)
}
/**

View File

@@ -6,26 +6,6 @@ private import semmle.code.cpp.models.interfaces.Alias
private class IntValue = Ints::IntValue;
/**
* Converts the bit count in `bits` to a byte count and a bit count in the form
* bytes:bits.
*/
bindingset[bits]
string bitsToBytesAndBits(int bits) { result = (bits / 8).toString() + ":" + (bits % 8).toString() }
/**
* Gets a printable string for a bit offset with possibly unknown value.
*/
bindingset[bitOffset]
string getBitOffsetString(IntValue bitOffset) {
if Ints::hasValue(bitOffset)
then
if bitOffset >= 0
then result = "+" + bitsToBytesAndBits(bitOffset)
else result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset))
else result = "+?"
}
/**
* Gets the offset of field `field` in bits.
*/
@@ -137,7 +117,11 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
or
// Adding an integer to or subtracting an integer from a pointer propagates
// the address with an offset.
bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction))
exists(PointerOffsetInstruction ptrOffset |
ptrOffset = instr and
operand = ptrOffset.getLeftOperand() and
bitOffset = getPointerBitOffset(ptrOffset)
)
or
// Computing a field address from a pointer propagates the address plus the
// offset of the field.

View File

@@ -865,3 +865,17 @@ private module CachedForDebugging {
result.getTag() = var.getTag()
}
}
module SSASanity {
query predicate multipleOperandMemoryLocations(
OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText
) {
exists(int locationCount |
locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and
locationCount > 1 and
func = operand.getEnclosingIRFunction() and
funcText = Language::getIdentityString(func.getFunction()) and
message = "Operand has " + locationCount.toString() + " memory accesses in function '$@'."
)
}
}

View File

@@ -0,0 +1,8 @@
/**
* @name Unaliased SSA Sanity Check
* @description Performs sanity checks on the SSA construction. This query should have no results.
* @kind table
* @id cpp/unaliased-ssa-sanity-check
*/
import SSASanity

View File

@@ -0,0 +1,2 @@
private import SSAConstruction as SSA
import SSA::SSASanity

View File

@@ -192,3 +192,33 @@ predicate isGT(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a > b }
*/
bindingset[a, b]
predicate isGE(IntValue a, IntValue b) { hasValue(a) and hasValue(b) and a >= b }
/**
* Converts the bit count in `bits` to a byte count and a bit count in the form
* "bytes:bits". If `bits` represents an integer number of bytes, the ":bits" section is omitted.
* If `bits` does not have a known value, the result is "?".
*/
bindingset[bits]
string bitsToBytesAndBits(IntValue bits) {
exists(int bytes, int leftoverBits |
hasValue(bits) and
bytes = bits / 8 and
leftoverBits = bits % 8 and
if leftoverBits = 0 then result = bytes.toString() else result = bytes + ":" + leftoverBits
)
or
not hasValue(bits) and result = "?"
}
/**
* Gets a printable string for a bit offset with possibly unknown value.
*/
bindingset[bitOffset]
string getBitOffsetString(IntValue bitOffset) {
if hasValue(bitOffset)
then
if bitOffset >= 0
then result = "+" + bitsToBytesAndBits(bitOffset)
else result = "-" + bitsToBytesAndBits(neg(bitOffset))
else result = "+?"
}

View File

@@ -30,5 +30,5 @@ Overlap getOverlap(IntValue defStart, IntValue defEnd, IntValue useStart, IntVal
bindingset[start, end]
string getIntervalString(IntValue start, IntValue end) {
// We represent an interval has half-open, so print it as "[start..end)".
result = "[" + intValueToString(start) + ".." + intValueToString(end) + ")"
result = "[" + bitsToBytesAndBits(start) + ".." + bitsToBytesAndBits(end) + ")"
}

View File

@@ -1,63 +1,63 @@
| BarrierGuard.cpp:9:10:9:15 | Load: source | BarrierGuard.cpp:5:19:5:24 | InitializeParameter: source |
| BarrierGuard.cpp:15:10:15:15 | Load: source | BarrierGuard.cpp:13:17:13:22 | InitializeParameter: source |
| BarrierGuard.cpp:25:10:25:15 | Load: source | BarrierGuard.cpp:21:17:21:22 | InitializeParameter: source |
| BarrierGuard.cpp:31:10:31:15 | Load: source | BarrierGuard.cpp:29:16:29:21 | InitializeParameter: source |
| BarrierGuard.cpp:33:10:33:15 | Load: source | BarrierGuard.cpp:29:16:29:21 | InitializeParameter: source |
| BarrierGuard.cpp:53:13:53:13 | Load: x | BarrierGuard.cpp:49:10:49:15 | Call: call to source |
| BarrierGuard.cpp:55:13:55:13 | Load: x | BarrierGuard.cpp:49:10:49:15 | Call: call to source |
| acrossLinkTargets.cpp:12:8:12:8 | Convert: (int)... | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source |
| acrossLinkTargets.cpp:12:8:12:8 | Load: x | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source |
| clang.cpp:18:8:18:19 | Convert: (const int *)... | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 |
| clang.cpp:18:8:18:19 | Load: sourceArray1 | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 |
| clang.cpp:37:10:37:11 | Load: m2 | clang.cpp:34:32:34:37 | Call: call to source |
| clang.cpp:41:18:41:19 | Load: m2 | clang.cpp:39:42:39:47 | Call: call to source |
| clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source |
| dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:37:19:37:24 | Call: call to source |
| dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:45:18:45:23 | Call: call to source |
| dispatch.cpp:23:38:23:38 | Load: x | dispatch.cpp:33:18:33:23 | Call: call to source |
| dispatch.cpp:23:38:23:38 | Load: x | dispatch.cpp:41:17:41:22 | Call: call to source |
| dispatch.cpp:31:16:31:24 | Call: call to isSource1 | dispatch.cpp:22:37:22:42 | Call: call to source |
| dispatch.cpp:32:16:32:24 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source |
| dispatch.cpp:35:16:35:25 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source |
| dispatch.cpp:36:16:36:25 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source |
| dispatch.cpp:39:15:39:23 | Call: call to isSource1 | dispatch.cpp:22:37:22:42 | Call: call to source |
| dispatch.cpp:40:15:40:23 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source |
| dispatch.cpp:43:15:43:24 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source |
| dispatch.cpp:44:15:44:24 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source |
| test.cpp:7:8:7:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:9:8:9:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:10:8:10:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:15:8:15:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:26:8:26:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:30:8:30:8 | Load: t | test.cpp:35:10:35:15 | Call: call to source |
| test.cpp:31:8:31:8 | Load: c | test.cpp:36:13:36:18 | Call: call to source |
| test.cpp:58:10:58:10 | Load: t | test.cpp:50:14:50:19 | Call: call to source |
| test.cpp:71:8:71:9 | Load: x4 | test.cpp:66:30:66:36 | InitializeParameter: source1 |
| test.cpp:76:8:76:9 | Load: u1 | test.cpp:75:7:75:8 | Uninitialized: definition of u1 |
| test.cpp:84:8:84:18 | Load: ... ? ... : ... | test.cpp:83:7:83:8 | Uninitialized: definition of u2 |
| test.cpp:86:8:86:9 | Load: i1 | test.cpp:83:7:83:8 | Uninitialized: definition of u2 |
| test.cpp:90:8:90:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 |
| test.cpp:92:8:92:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 |
| test.cpp:110:10:110:12 | Load: (reference dereference) | test.cpp:109:9:109:14 | Call: call to source |
| test.cpp:140:8:140:8 | Load: y | test.cpp:138:27:138:32 | Call: call to source |
| test.cpp:144:8:144:8 | Load: s | test.cpp:151:33:151:38 | Call: call to source |
| test.cpp:152:8:152:8 | Load: y | test.cpp:151:33:151:38 | Call: call to source |
| test.cpp:157:8:157:8 | Load: x | test.cpp:164:34:164:39 | Call: call to source |
| test.cpp:165:8:165:8 | Load: y | test.cpp:164:34:164:39 | Call: call to source |
| test.cpp:178:8:178:8 | Load: y | test.cpp:171:11:171:16 | Call: call to source |
| test.cpp:260:12:260:12 | Load: x | test.cpp:245:14:245:19 | Call: call to source |
| test.cpp:266:12:266:12 | Load: x | test.cpp:265:22:265:27 | Call: call to source |
| test.cpp:289:14:289:14 | Load: x | test.cpp:305:17:305:22 | Call: call to source |
| test.cpp:318:7:318:7 | Load: x | test.cpp:314:4:314:9 | Call: call to source |
| test.cpp:450:9:450:22 | CopyValue: (statement expression) | test.cpp:449:26:449:32 | InitializeParameter: source1 |
| test.cpp:461:8:461:12 | Load: local | test.cpp:449:26:449:32 | InitializeParameter: source1 |
| true_upon_entry.cpp:13:8:13:8 | Load: x | true_upon_entry.cpp:9:11:9:16 | Call: call to source |
| true_upon_entry.cpp:21:8:21:8 | Load: x | true_upon_entry.cpp:17:11:17:16 | Call: call to source |
| true_upon_entry.cpp:29:8:29:8 | Load: x | true_upon_entry.cpp:27:9:27:14 | Call: call to source |
| true_upon_entry.cpp:39:8:39:8 | Load: x | true_upon_entry.cpp:33:11:33:16 | Call: call to source |
| true_upon_entry.cpp:49:8:49:8 | Load: x | true_upon_entry.cpp:43:11:43:16 | Call: call to source |
| true_upon_entry.cpp:57:8:57:8 | Load: x | true_upon_entry.cpp:54:11:54:16 | Call: call to source |
| true_upon_entry.cpp:66:8:66:8 | Load: x | true_upon_entry.cpp:62:11:62:16 | Call: call to source |
| true_upon_entry.cpp:78:8:78:8 | Load: x | true_upon_entry.cpp:70:11:70:16 | Call: call to source |
| true_upon_entry.cpp:86:8:86:8 | Load: x | true_upon_entry.cpp:83:11:83:16 | Call: call to source |
| true_upon_entry.cpp:105:8:105:8 | Load: x | true_upon_entry.cpp:98:11:98:16 | Call: call to source |
| BarrierGuard.cpp:9:10:9:15 | source | BarrierGuard.cpp:5:19:5:24 | source |
| BarrierGuard.cpp:15:10:15:15 | source | BarrierGuard.cpp:13:17:13:22 | source |
| BarrierGuard.cpp:25:10:25:15 | source | BarrierGuard.cpp:21:17:21:22 | source |
| BarrierGuard.cpp:31:10:31:15 | source | BarrierGuard.cpp:29:16:29:21 | source |
| BarrierGuard.cpp:33:10:33:15 | source | BarrierGuard.cpp:29:16:29:21 | source |
| BarrierGuard.cpp:53:13:53:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
| BarrierGuard.cpp:55:13:55:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
| acrossLinkTargets.cpp:12:8:12:8 | (int)... | acrossLinkTargets.cpp:19:27:19:32 | call to source |
| acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source |
| clang.cpp:18:8:18:19 | (const int *)... | clang.cpp:12:9:12:20 | sourceArray1 |
| clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 |
| clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source |
| clang.cpp:41:18:41:19 | m2 | clang.cpp:39:42:39:47 | call to source |
| clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source |
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:37:19:37:24 | call to source |
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:45:18:45:23 | call to source |
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:33:18:33:23 | call to source |
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:41:17:41:22 | call to source |
| dispatch.cpp:31:16:31:24 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
| dispatch.cpp:32:16:32:24 | call to isSource2 | dispatch.cpp:16:37:16:42 | call to source |
| dispatch.cpp:35:16:35:25 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
| dispatch.cpp:36:16:36:25 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source |
| dispatch.cpp:39:15:39:23 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
| dispatch.cpp:40:15:40:23 | call to isSource2 | dispatch.cpp:16:37:16:42 | call to source |
| dispatch.cpp:43:15:43:24 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
| dispatch.cpp:44:15:44:24 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source |
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
| test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source |
| test.cpp:15:8:15:9 | t2 | test.cpp:6:12:6:17 | call to source |
| test.cpp:26:8:26:9 | t1 | test.cpp:6:12:6:17 | call to source |
| test.cpp:30:8:30:8 | t | test.cpp:35:10:35:15 | call to source |
| test.cpp:31:8:31:8 | c | test.cpp:36:13:36:18 | call to source |
| test.cpp:58:10:58:10 | t | test.cpp:50:14:50:19 | call to source |
| test.cpp:71:8:71:9 | x4 | test.cpp:66:30:66:36 | source1 |
| test.cpp:76:8:76:9 | u1 | test.cpp:75:7:75:8 | u1 |
| test.cpp:84:8:84:18 | ... ? ... : ... | test.cpp:83:7:83:8 | u2 |
| test.cpp:86:8:86:9 | i1 | test.cpp:83:7:83:8 | u2 |
| test.cpp:90:8:90:14 | source1 | test.cpp:89:28:89:34 | source1 |
| test.cpp:92:8:92:14 | source1 | test.cpp:89:28:89:34 | source1 |
| test.cpp:110:10:110:12 | (reference dereference) | test.cpp:109:9:109:14 | call to source |
| test.cpp:140:8:140:8 | y | test.cpp:138:27:138:32 | call to source |
| test.cpp:144:8:144:8 | s | test.cpp:151:33:151:38 | call to source |
| test.cpp:152:8:152:8 | y | test.cpp:151:33:151:38 | call to source |
| test.cpp:157:8:157:8 | x | test.cpp:164:34:164:39 | call to source |
| test.cpp:165:8:165:8 | y | test.cpp:164:34:164:39 | call to source |
| test.cpp:178:8:178:8 | y | test.cpp:171:11:171:16 | call to source |
| test.cpp:260:12:260:12 | x | test.cpp:245:14:245:19 | call to source |
| test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source |
| test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source |
| test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source |
| test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 |
| test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 |
| true_upon_entry.cpp:13:8:13:8 | x | true_upon_entry.cpp:9:11:9:16 | call to source |
| true_upon_entry.cpp:21:8:21:8 | x | true_upon_entry.cpp:17:11:17:16 | call to source |
| true_upon_entry.cpp:29:8:29:8 | x | true_upon_entry.cpp:27:9:27:14 | call to source |
| true_upon_entry.cpp:39:8:39:8 | x | true_upon_entry.cpp:33:11:33:16 | call to source |
| true_upon_entry.cpp:49:8:49:8 | x | true_upon_entry.cpp:43:11:43:16 | call to source |
| true_upon_entry.cpp:57:8:57:8 | x | true_upon_entry.cpp:54:11:54:16 | call to source |
| true_upon_entry.cpp:66:8:66:8 | x | true_upon_entry.cpp:62:11:62:16 | call to source |
| true_upon_entry.cpp:78:8:78:8 | x | true_upon_entry.cpp:70:11:70:16 | call to source |
| true_upon_entry.cpp:86:8:86:8 | x | true_upon_entry.cpp:83:11:83:16 | call to source |
| true_upon_entry.cpp:105:8:105:8 | x | true_upon_entry.cpp:98:11:98:16 | call to source |

View File

@@ -78,15 +78,15 @@ edges
| B.cpp:19:14:19:17 | box1 [elem2] | B.cpp:19:20:19:24 | elem2 |
| C.cpp:18:12:18:18 | call to C [s1] | C.cpp:19:5:19:5 | c [s1] |
| C.cpp:18:12:18:18 | call to C [s3] | C.cpp:19:5:19:5 | c [s3] |
| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | `this` parameter in func [s1] |
| C.cpp:19:5:19:5 | c [s3] | C.cpp:27:8:27:11 | `this` parameter in func [s3] |
| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | this [s1] |
| C.cpp:19:5:19:5 | c [s3] | C.cpp:27:8:27:11 | this [s3] |
| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | C.cpp:18:12:18:18 | call to C [s1] |
| C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] |
| C.cpp:24:5:24:8 | this [post update] [s3] | C.cpp:18:12:18:18 | call to C [s3] |
| C.cpp:24:5:24:25 | ... = ... | C.cpp:24:5:24:8 | this [post update] [s3] |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | ... = ... |
| C.cpp:27:8:27:11 | `this` parameter in func [s1] | C.cpp:29:10:29:11 | this [s1] |
| C.cpp:27:8:27:11 | `this` parameter in func [s3] | C.cpp:31:10:31:11 | this [s3] |
| C.cpp:27:8:27:11 | this [s1] | C.cpp:29:10:29:11 | this [s1] |
| C.cpp:27:8:27:11 | this [s3] | C.cpp:31:10:31:11 | this [s3] |
| C.cpp:29:10:29:11 | this [s1] | C.cpp:29:10:29:11 | s1 |
| C.cpp:31:10:31:11 | this [s3] | C.cpp:31:10:31:11 | s3 |
| D.cpp:21:30:21:31 | b2 [box, elem] | D.cpp:22:10:22:11 | b2 [box, elem] |
@@ -117,8 +117,8 @@ edges
| D.cpp:58:5:58:12 | this [post update] [boxfield, box, ... (3)] | D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] |
| D.cpp:58:5:58:27 | ... = ... | D.cpp:58:15:58:17 | box [post update] [elem] |
| D.cpp:58:15:58:17 | box [post update] [elem] | D.cpp:58:5:58:12 | boxfield [post update] [box, elem] |
| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] |
| D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] |
| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] |
| D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] |
| D.cpp:64:10:64:17 | boxfield [box, elem] | D.cpp:64:20:64:22 | box [elem] |
| D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | boxfield [box, elem] |
| D.cpp:64:20:64:22 | box [elem] | D.cpp:64:25:64:28 | elem |
@@ -337,8 +337,8 @@ nodes
| C.cpp:24:5:24:8 | this [post update] [s3] | semmle.label | this [post update] [s3] |
| C.cpp:24:5:24:25 | ... = ... | semmle.label | ... = ... |
| C.cpp:24:16:24:25 | new | semmle.label | new |
| C.cpp:27:8:27:11 | `this` parameter in func [s1] | semmle.label | `this` parameter in func [s1] |
| C.cpp:27:8:27:11 | `this` parameter in func [s3] | semmle.label | `this` parameter in func [s3] |
| C.cpp:27:8:27:11 | this [s1] | semmle.label | this [s1] |
| C.cpp:27:8:27:11 | this [s3] | semmle.label | this [s3] |
| C.cpp:29:10:29:11 | s1 | semmle.label | s1 |
| C.cpp:29:10:29:11 | this [s1] | semmle.label | this [s1] |
| C.cpp:31:10:31:11 | s3 | semmle.label | s3 |
@@ -373,7 +373,7 @@ nodes
| D.cpp:58:5:58:27 | ... = ... | semmle.label | ... = ... |
| D.cpp:58:15:58:17 | box [post update] [elem] | semmle.label | box [post update] [elem] |
| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
| D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] | semmle.label | `this` parameter in f5b [boxfield, box, ... (3)] |
| D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
| D.cpp:64:10:64:17 | boxfield [box, elem] | semmle.label | boxfield [box, elem] |
| D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
| D.cpp:64:20:64:22 | box [elem] | semmle.label | box [elem] |

View File

@@ -45,7 +45,7 @@
| taint.cpp:37:12:37:20 | call to increment | taint.cpp:43:7:43:13 | global9 | |
| taint.cpp:38:13:38:16 | call to zero | taint.cpp:38:2:38:26 | ... = ... | |
| taint.cpp:38:13:38:16 | call to zero | taint.cpp:44:7:44:14 | global10 | |
| taint.cpp:71:2:71:8 | `this` parameter in MyClass | taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | |
| taint.cpp:71:2:71:8 | this | taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | |
| taint.cpp:71:14:71:17 | 0 | taint.cpp:71:14:71:17 | constructor init of field a | TAINT |
| taint.cpp:71:14:71:17 | constructor init of field a [post-this] | taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | |
| taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | |
@@ -56,7 +56,7 @@
| taint.cpp:72:3:72:3 | this [post update] | taint.cpp:73:3:73:3 | this | |
| taint.cpp:72:7:72:12 | call to source | taint.cpp:72:3:72:14 | ... = ... | |
| taint.cpp:73:7:73:7 | 0 | taint.cpp:73:3:73:7 | ... = ... | |
| taint.cpp:76:7:76:14 | `this` parameter in myMethod | taint.cpp:77:3:77:3 | this | |
| taint.cpp:76:7:76:14 | this | taint.cpp:77:3:77:3 | this | |
| taint.cpp:77:7:77:12 | call to source | taint.cpp:77:3:77:14 | ... = ... | |
| taint.cpp:84:10:84:12 | call to MyClass | taint.cpp:86:2:86:4 | mc1 | |
| taint.cpp:84:10:84:12 | call to MyClass | taint.cpp:88:7:88:9 | mc1 | |
@@ -178,51 +178,51 @@
| taint.cpp:213:15:213:15 | ref arg y | taint.cpp:216:7:216:7 | y | |
| taint.cpp:213:15:213:15 | y | taint.cpp:213:12:213:12 | ref arg x | |
| taint.cpp:223:10:223:15 | call to source | taint.cpp:228:12:228:12 | t | |
| taint.cpp:223:10:223:15 | call to source | taint.cpp:235:11:239:2 | t | |
| taint.cpp:223:10:223:15 | call to source | taint.cpp:243:11:246:2 | t | |
| taint.cpp:223:10:223:15 | call to source | taint.cpp:235:10:239:2 | t | |
| taint.cpp:223:10:223:15 | call to source | taint.cpp:243:10:246:2 | t | |
| taint.cpp:223:10:223:15 | call to source | taint.cpp:253:4:253:4 | t | |
| taint.cpp:223:10:223:15 | call to source | taint.cpp:260:4:260:4 | t | |
| taint.cpp:224:9:224:10 | 0 | taint.cpp:228:15:228:15 | u | |
| taint.cpp:224:9:224:10 | 0 | taint.cpp:235:11:239:2 | u | |
| taint.cpp:224:9:224:10 | 0 | taint.cpp:243:11:246:2 | u | |
| taint.cpp:224:9:224:10 | 0 | taint.cpp:235:10:239:2 | u | |
| taint.cpp:224:9:224:10 | 0 | taint.cpp:243:10:246:2 | u | |
| taint.cpp:224:9:224:10 | 0 | taint.cpp:253:7:253:7 | u | |
| taint.cpp:224:9:224:10 | 0 | taint.cpp:260:7:260:7 | u | |
| taint.cpp:225:9:225:10 | 0 | taint.cpp:235:11:239:2 | v | |
| taint.cpp:225:9:225:10 | 0 | taint.cpp:235:10:239:2 | v | |
| taint.cpp:225:9:225:10 | 0 | taint.cpp:241:7:241:7 | v | |
| taint.cpp:226:9:226:10 | 0 | taint.cpp:260:10:260:10 | w | |
| taint.cpp:226:9:226:10 | 0 | taint.cpp:261:7:261:7 | w | |
| taint.cpp:228:10:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | |
| taint.cpp:228:10:232:2 | {...} | taint.cpp:228:10:232:2 | [...](...){...} | |
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field t | TAINT |
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field u | TAINT |
| taint.cpp:228:11:228:11 | `this` parameter in (constructor) | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | |
| taint.cpp:228:11:228:11 | constructor init of field t [post-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
| taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
| taint.cpp:228:11:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | |
| taint.cpp:228:11:232:2 | {...} | taint.cpp:228:11:232:2 | [...](...){...} | |
| taint.cpp:228:17:228:17 | `this` parameter in operator() | taint.cpp:229:3:229:6 | this | |
| taint.cpp:228:11:228:11 | this | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | |
| taint.cpp:228:17:228:17 | this | taint.cpp:229:3:229:6 | this | |
| taint.cpp:229:3:229:6 | this | taint.cpp:230:3:230:6 | this | |
| taint.cpp:230:3:230:6 | this | taint.cpp:231:3:231:11 | this | |
| taint.cpp:235:10:239:2 | [...](...){...} | taint.cpp:240:2:240:2 | b | |
| taint.cpp:235:10:239:2 | {...} | taint.cpp:235:10:239:2 | [...](...){...} | |
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field t | TAINT |
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field u | TAINT |
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field v | TAINT |
| taint.cpp:235:11:235:11 | `this` parameter in (constructor) | taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | |
| taint.cpp:235:11:235:11 | constructor init of field t [post-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | |
| taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | |
| taint.cpp:235:11:235:11 | constructor init of field u [post-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | |
| taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | |
| taint.cpp:235:11:239:2 | [...](...){...} | taint.cpp:240:2:240:2 | b | |
| taint.cpp:235:11:239:2 | {...} | taint.cpp:235:11:239:2 | [...](...){...} | |
| taint.cpp:235:15:235:15 | `this` parameter in operator() | taint.cpp:236:3:236:6 | this | |
| taint.cpp:235:11:235:11 | this | taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | |
| taint.cpp:235:15:235:15 | this | taint.cpp:236:3:236:6 | this | |
| taint.cpp:236:3:236:6 | this | taint.cpp:237:3:237:6 | this | |
| taint.cpp:237:3:237:6 | this | taint.cpp:238:3:238:14 | this | |
| taint.cpp:238:7:238:12 | call to source | taint.cpp:238:3:238:14 | ... = ... | |
| taint.cpp:243:10:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | |
| taint.cpp:243:10:246:2 | {...} | taint.cpp:243:10:246:2 | [...](...){...} | |
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field t | TAINT |
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field u | TAINT |
| taint.cpp:243:11:243:11 | `this` parameter in (constructor) | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | |
| taint.cpp:243:11:243:11 | constructor init of field t [post-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
| taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
| taint.cpp:243:11:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | |
| taint.cpp:243:11:246:2 | {...} | taint.cpp:243:11:246:2 | [...](...){...} | |
| taint.cpp:243:15:243:15 | `this` parameter in operator() | taint.cpp:244:3:244:6 | this | |
| taint.cpp:243:11:243:11 | this | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | |
| taint.cpp:243:15:243:15 | this | taint.cpp:244:3:244:6 | this | |
| taint.cpp:244:3:244:6 | this | taint.cpp:245:3:245:6 | this | |
| taint.cpp:249:11:252:2 | [...](...){...} | taint.cpp:253:2:253:2 | d | |
| taint.cpp:249:18:249:18 | a | taint.cpp:250:8:250:8 | a | |

View File

@@ -1,16 +1,16 @@
| taint.cpp:8:8:8:13 | Load: clean1 | taint.cpp:4:27:4:33 | InitializeParameter: source1 |
| taint.cpp:16:8:16:14 | Load: source1 | taint.cpp:12:22:12:27 | Call: call to source |
| taint.cpp:17:8:17:16 | Add: ++ ... | taint.cpp:12:22:12:27 | Call: call to source |
| taint.cpp:109:7:109:13 | Load: access to array | taint.cpp:105:12:105:17 | Call: call to source |
| taint.cpp:129:7:129:9 | Load: * ... | taint.cpp:120:11:120:16 | Call: call to source |
| taint.cpp:130:7:130:9 | Load: * ... | taint.cpp:127:8:127:13 | Call: call to source |
| taint.cpp:134:7:134:9 | Load: * ... | taint.cpp:120:11:120:16 | Call: call to source |
| taint.cpp:151:7:151:12 | Call: call to select | taint.cpp:151:20:151:25 | Call: call to source |
| taint.cpp:167:8:167:13 | Call: call to source | taint.cpp:167:8:167:13 | Call: call to source |
| taint.cpp:168:8:168:14 | Load: tainted | taint.cpp:164:19:164:24 | Call: call to source |
| taint.cpp:210:7:210:7 | Load: x | taint.cpp:207:6:207:11 | Call: call to source |
| taint.cpp:280:7:280:7 | Load: t | taint.cpp:275:6:275:11 | Call: call to source |
| taint.cpp:289:7:289:7 | Load: t | taint.cpp:275:6:275:11 | Call: call to source |
| taint.cpp:290:7:290:7 | Load: x | taint.cpp:275:6:275:11 | Call: call to source |
| taint.cpp:291:7:291:7 | Load: y | taint.cpp:275:6:275:11 | Call: call to source |
| taint.cpp:337:7:337:7 | Load: t | taint.cpp:330:6:330:11 | Call: call to source |
| taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 |
| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source |
| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source |
| taint.cpp:109:7:109:13 | access to array | taint.cpp:105:12:105:17 | call to source |
| taint.cpp:129:7:129:9 | * ... | taint.cpp:120:11:120:16 | call to source |
| taint.cpp:130:7:130:9 | * ... | taint.cpp:127:8:127:13 | call to source |
| taint.cpp:134:7:134:9 | * ... | taint.cpp:120:11:120:16 | call to source |
| taint.cpp:151:7:151:12 | call to select | taint.cpp:151:20:151:25 | call to source |
| taint.cpp:167:8:167:13 | call to source | taint.cpp:167:8:167:13 | call to source |
| taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source |
| taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source |
| taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:290:7:290:7 | x | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:291:7:291:7 | y | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:337:7:337:7 | t | taint.cpp:330:6:330:11 | call to source |

View File

@@ -11,8 +11,8 @@
| addressOf.cpp:31:23:31:23 | i | addressOf.cpp:38:20:38:25 | ... += ... |
| addressOf.cpp:40:8:40:11 | iref | addressOf.cpp:40:15:40:15 | i |
| addressOf.cpp:40:8:40:11 | iref | addressOf.cpp:42:18:42:22 | & ... |
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:13:47:31 | [...](...){...} |
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:13:49:39 | [...](...){...} |
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:12:47:31 | [...](...){...} |
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:12:49:39 | [...](...){...} |
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:56:13:56:28 | {...} |
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:57:18:57:45 | ... + ... |
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:58:18:58:18 | a |

View File

@@ -8,8 +8,8 @@
| addressOf.cpp:31:23:31:23 | i | addressOf.cpp:37:18:37:26 | & ... | addressOf.cpp:38:20:38:20 | i |
| addressOf.cpp:31:23:31:23 | i | addressOf.cpp:38:18:38:30 | ... + ... | addressOf.cpp:40:15:40:15 | i |
| addressOf.cpp:40:8:40:11 | iref | addressOf.cpp:40:15:40:15 | i | addressOf.cpp:42:19:42:22 | iref |
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:13:47:31 | [...](...){...} | addressOf.cpp:48:3:48:4 | f1 |
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:13:49:39 | [...](...){...} | addressOf.cpp:50:3:50:4 | f2 |
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:12:47:31 | [...](...){...} | addressOf.cpp:48:3:48:4 | f1 |
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:12:49:39 | [...](...){...} | addressOf.cpp:50:3:50:4 | f2 |
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:56:13:56:28 | {...} | addressOf.cpp:57:19:57:19 | a |
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:57:18:57:45 | ... + ... | addressOf.cpp:58:18:58:18 | a |
| indirect_use.cpp:20:10:20:10 | p | indirect_use.cpp:20:14:20:15 | ip | indirect_use.cpp:21:17:21:17 | p |

View File

@@ -1,5 +1,5 @@
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:13:47:31 | [...](...){...} | addressOf.cpp:47:13:47:31 | [...](...){...} |
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:13:49:39 | [...](...){...} | addressOf.cpp:49:13:49:39 | [...](...){...} |
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:12:47:31 | [...](...){...} | addressOf.cpp:47:12:47:31 | [...](...){...} |
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:12:49:39 | [...](...){...} | addressOf.cpp:49:12:49:39 | [...](...){...} |
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:56:13:56:28 | {...} | addressOf.cpp:56:13:56:28 | {...} |
| indirect_use.cpp:20:10:20:10 | p | indirect_use.cpp:20:14:20:15 | ip | indirect_use.cpp:20:14:20:15 | ip |
| indirect_use.cpp:25:10:25:10 | p | indirect_use.cpp:25:14:25:19 | ... + ... | indirect_use.cpp:25:14:25:19 | ... + ... |

View File

@@ -1,86 +1,86 @@
| escape.cpp:111:18:111:21 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 |
| escape.cpp:115:20:115:23 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 |
| escape.cpp:116:20:116:23 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 |
| escape.cpp:117:23:117:26 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:118:9:118:12 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:120:12:120:15 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:123:14:123:17 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:124:15:124:18 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:127:9:127:12 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:129:12:129:15 | CopyValue | no_+0:0 | no_+0:0 |
| escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:134:11:134:18 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:135:5:135:12 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
| escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
| escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
| escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 |
| escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 |
| escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 |
| escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 |
| escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:143:19:143:27 | CopyValue | no_Point+0:0 | no_Point+0:0 |
| escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:144:6:144:14 | CopyValue | no_Point+0:0 | no_Point+0:0 |
| escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 |
| escape.cpp:145:20:145:30 | CopyValue | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 |
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 |
| escape.cpp:151:5:151:14 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
| escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
| escape.cpp:152:19:152:28 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 |
| escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 |
| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |
| escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 |
| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 |
| escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 |
| escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 |
| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
| escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
| escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 |
| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 |
| escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 |
| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0:0 | passByPtr+0:0 |
| escape.cpp:170:21:170:29 | CopyValue | passByRef+0:0 | passByRef+0:0 |
| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 |
| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 |
| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 |
| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 |
| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0:0 | passByPtr2+0:0 |
| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0:0 | passByRef2+0:0 |
| escape.cpp:191:30:191:42 | Call | none | passByPtr3+0:0 |
| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0:0 | passByPtr3+0:0 |
| escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 |
| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0:0 |
| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0:0 | passByRef3+0:0 |
| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 |
| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 |
| escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 |
| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0:0 |
| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0:0 | passByRef6+0:0 |
| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0:0 |
| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0:0 |
| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 |
| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0:0 |
| escape.cpp:217:14:217:16 | CopyValue | c2+0:0 | c2+0:0 |
| escape.cpp:221:8:221:19 | Call | none | c3+0:0 |
| escape.cpp:225:17:225:28 | Call | none | c4+0:0 |
| escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 |
| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0:0 | condEscape1+0:0 |
| escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 |
| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0:0 | condEscape2+0:0 |
| escape.cpp:111:18:111:21 | CopyValue | no_+0 | no_+0 |
| escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0 | no_+0 |
| escape.cpp:115:20:115:23 | CopyValue | no_+0 | no_+0 |
| escape.cpp:116:19:116:28 | PointerSub[4] | no_+0 | no_+0 |
| escape.cpp:116:20:116:23 | CopyValue | no_+0 | no_+0 |
| escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0 | no_+0 |
| escape.cpp:117:23:117:26 | CopyValue | no_+0 | no_+0 |
| escape.cpp:118:9:118:12 | CopyValue | no_+0 | no_+0 |
| escape.cpp:120:12:120:15 | CopyValue | no_+0 | no_+0 |
| escape.cpp:123:14:123:17 | CopyValue | no_+0 | no_+0 |
| escape.cpp:124:15:124:18 | CopyValue | no_+0 | no_+0 |
| escape.cpp:127:9:127:12 | CopyValue | no_+0 | no_+0 |
| escape.cpp:129:12:129:15 | CopyValue | no_+0 | no_+0 |
| escape.cpp:134:5:134:18 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:134:11:134:18 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:135:5:135:12 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20 | no_Array+20 |
| escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20 | no_Array+20 |
| escape.cpp:136:7:136:14 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:137:17:137:24 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20 | no_Array+20 |
| escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20 | no_Array+20 |
| escape.cpp:138:19:138:26 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0 | no_Point+0 |
| escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4 | no_Point+4 |
| escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8 | no_Point+8 |
| escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0 | no_Point+0 |
| escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4 | no_Point+4 |
| escape.cpp:143:19:143:27 | CopyValue | no_Point+0 | no_Point+0 |
| escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4 | no_Point+4 |
| escape.cpp:144:6:144:14 | CopyValue | no_Point+0 | no_Point+0 |
| escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4 | no_Point+4 |
| escape.cpp:145:20:145:30 | CopyValue | no_Point+8 | no_Point+8 |
| escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8 | no_Point+8 |
| escape.cpp:146:5:146:18 | CopyValue | no_Point+8 | no_Point+8 |
| escape.cpp:146:7:146:17 | CopyValue | no_Point+8 | no_Point+8 |
| escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8 | no_Point+8 |
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0 | no_Derived+0 |
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0 | no_Derived+0 |
| escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0 | no_Derived+0 |
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0 | no_Derived+0 |
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0 | no_Derived+0 |
| escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0 | no_Derived+0 |
| escape.cpp:151:5:151:14 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12 | no_Derived+12 |
| escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16 | no_Derived+16 |
| escape.cpp:152:19:152:28 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12 | no_Derived+12 |
| escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16 | no_Derived+16 |
| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0 | no_ssa_addrOf+0 |
| escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0 | no_ssa_addrOf+0 |
| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0 | no_ssa_refTo+0 |
| escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0 | no_ssa_refTo+0 |
| escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0 | no_ssa_refToArrayElement+0 |
| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20 | no_ssa_refToArrayElement+20 |
| escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20 | no_ssa_refToArrayElement+20 |
| escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20 | no_ssa_refToArrayElement+20 |
| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0 | no_ssa_refToArray+0 |
| escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0 | no_ssa_refToArray+0 |
| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0 | passByPtr+0 |
| escape.cpp:170:21:170:29 | CopyValue | passByRef+0 | passByRef+0 |
| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0 | no_ssa_passByPtr+0 |
| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0 | no_ssa_passByRef+0 |
| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0 | no_ssa_passByPtr_ret+0 |
| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0 | no_ssa_passByRef_ret+0 |
| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0 | passByPtr2+0 |
| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0 | passByRef2+0 |
| escape.cpp:191:30:191:42 | Call | none | passByPtr3+0 |
| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0 | passByPtr3+0 |
| escape.cpp:194:32:194:46 | Call | none | passByRef3+0 |
| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0 |
| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0 | passByRef3+0 |
| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0 | no_ssa_passByPtr4+0 |
| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0 | no_ssa_passByPtr5+0 |
| escape.cpp:202:5:202:19 | Call | none | passByRef6+0 |
| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0 |
| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0 | passByRef6+0 |
| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0 |
| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0 |
| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0 | no_ssa_passByRef7+0 |
| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0 |
| escape.cpp:217:14:217:16 | CopyValue | c2+0 | c2+0 |
| escape.cpp:221:8:221:19 | Call | none | c3+0 |
| escape.cpp:225:17:225:28 | Call | none | c4+0 |
| escape.cpp:247:2:247:27 | Store | condEscape1+0 | condEscape1+0 |
| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0 | condEscape1+0 |
| escape.cpp:249:9:249:34 | Store | condEscape2+0 | condEscape2+0 |
| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0 | condEscape2+0 |

View File

@@ -4,6 +4,7 @@ import semmle.code.cpp.ir.implementation.raw.IR as Raw
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.AliasAnalysis as UnAA
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as Un
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction
import semmle.code.cpp.ir.internal.IntegerConstant
from Raw::Instruction rawInstr, Un::Instruction unInstr, string rawPointsTo, string unPointsTo
where
@@ -12,21 +13,21 @@ where
(
exists(Variable var, int rawBitOffset, int unBitOffset |
RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), rawBitOffset) and
rawPointsTo = var.toString() + RawAA::getBitOffsetString(rawBitOffset) and
rawPointsTo = var.toString() + getBitOffsetString(rawBitOffset) and
UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), unBitOffset) and
unPointsTo = var.toString() + UnAA::getBitOffsetString(unBitOffset)
unPointsTo = var.toString() + getBitOffsetString(unBitOffset)
)
or
exists(Variable var, int unBitOffset |
not RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), _) and
rawPointsTo = "none" and
UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), unBitOffset) and
unPointsTo = var.toString() + UnAA::getBitOffsetString(unBitOffset)
unPointsTo = var.toString() + getBitOffsetString(unBitOffset)
)
or
exists(Variable var, int rawBitOffset |
RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), rawBitOffset) and
rawPointsTo = var.toString() + RawAA::getBitOffsetString(rawBitOffset) and
rawPointsTo = var.toString() + getBitOffsetString(rawBitOffset) and
not UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), _) and
unPointsTo = "none"
)

View File

@@ -3732,7 +3732,7 @@ ir.cpp:
# 572| Type = [ArrayType] char[32]
# 572| init: [Initializer] initializer for a_pad
# 572| expr:
# 572| Type = [ArrayType] const char[1]
# 572| Type = [ArrayType] const char[32]
# 572| Value = [StringLiteral] ""
# 572| ValueCategory = lvalue
# 573| 1: [DeclStmt] declaration
@@ -6894,9 +6894,6 @@ ir.cpp:
# 1029| params:
#-----| 0: [Parameter] p#0
#-----| Type = [RValueReferenceType] lambda [] type at line 1029, col. 12 &&
# 1029| initializations:
# 1029| body: [Block] { ... }
# 1029| 0: [ReturnStmt] return ...
# 1029| [Constructor] void (lambda [] type at line 1029, col. 12)::(constructor)()
# 1029| params:
# 1029| [MemberFunction] void (lambda [] type at line 1029, col. 12)::_FUN()
@@ -6996,24 +6993,18 @@ ir.cpp:
# 1036| 0: [VariableDeclarationEntry] definition of lambda_val
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
# 1036| init: [Initializer] initializer for lambda_val
# 1036| expr: [ConstructorCall] call to (constructor)
# 1036| Type = [VoidType] void
# 1036| expr: [LambdaExpression] [...](...){...}
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
# 1036| ValueCategory = prvalue
# 1036| 0: [ReferenceToExpr] (reference to)
# 1036| Type = [LValueReferenceType] lambda [] type at line 1036, col. 21 &
# 1036| 0: [ClassAggregateLiteral] {...}
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
# 1036| ValueCategory = prvalue
# 1036| expr: [LambdaExpression] [...](...){...}
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
# 1036| ValueCategory = xvalue
# 1036| 0: [ClassAggregateLiteral] {...}
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
# 1036| ValueCategory = prvalue
#-----| .s: [ConstructorCall] call to String
#-----| Type = [VoidType] void
#-----| ValueCategory = prvalue
#-----| .x: [VariableAccess] x
#-----| Type = [IntType] int
#-----| ValueCategory = prvalue(load)
#-----| .s: [ConstructorCall] call to String
#-----| Type = [VoidType] void
#-----| ValueCategory = prvalue
#-----| .x: [VariableAccess] x
#-----| Type = [IntType] int
#-----| ValueCategory = prvalue(load)
# 1037| 5: [ExprStmt] ExprStmt
# 1037| 0: [FunctionCall] call to operator()
# 1037| Type = [PlainCharType] char
@@ -7077,21 +7068,15 @@ ir.cpp:
# 1040| 0: [VariableDeclarationEntry] definition of lambda_val_explicit
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
# 1040| init: [Initializer] initializer for lambda_val_explicit
# 1040| expr: [ConstructorCall] call to (constructor)
# 1040| Type = [VoidType] void
# 1040| expr: [LambdaExpression] [...](...){...}
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
# 1040| ValueCategory = prvalue
# 1040| 0: [ReferenceToExpr] (reference to)
# 1040| Type = [LValueReferenceType] lambda [] type at line 1040, col. 30 &
# 1040| 0: [ClassAggregateLiteral] {...}
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
# 1040| ValueCategory = prvalue
# 1040| expr: [LambdaExpression] [...](...){...}
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
# 1040| ValueCategory = xvalue
# 1040| 0: [ClassAggregateLiteral] {...}
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
# 1040| ValueCategory = prvalue
#-----| .s: [ConstructorCall] call to String
#-----| Type = [VoidType] void
#-----| ValueCategory = prvalue
#-----| .s: [ConstructorCall] call to String
#-----| Type = [VoidType] void
#-----| ValueCategory = prvalue
# 1041| 9: [ExprStmt] ExprStmt
# 1041| 0: [FunctionCall] call to operator()
# 1041| Type = [PlainCharType] char
@@ -7239,9 +7224,6 @@ ir.cpp:
# 1032| params:
#-----| 0: [Parameter] p#0
#-----| Type = [RValueReferenceType] lambda [] type at line 1032, col. 23 &&
# 1032| initializations:
# 1032| body: [Block] { ... }
# 1032| 0: [ReturnStmt] return ...
# 1032| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)()
# 1032| params:
# 1032| [MemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::_FUN(float)
@@ -7277,21 +7259,6 @@ ir.cpp:
# 1034| params:
#-----| 0: [Parameter] p#0
#-----| Type = [RValueReferenceType] lambda [] type at line 1034, col. 21 &&
# 1034| initializations:
# 1034| 0: [ConstructorFieldInit] constructor init of field s
# 1034| Type = [LValueReferenceType] const String &
# 1034| ValueCategory = prvalue
# 1034| 0: [Literal] Unknown literal
# 1034| Type = [LValueReferenceType] const String &
# 1034| ValueCategory = prvalue
# 1034| 1: [ConstructorFieldInit] constructor init of field x
# 1034| Type = [LValueReferenceType] int &
# 1034| ValueCategory = prvalue
# 1034| 0: [Literal] Unknown literal
# 1034| Type = [LValueReferenceType] int &
# 1034| ValueCategory = prvalue
# 1034| body: [Block] { ... }
# 1034| 0: [ReturnStmt] return ...
# 1034| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1034, col. 21)::(constructor)()
# 1034| params:
# 1034| [ConstMemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1034, col. 21)::operator()(float) const
@@ -7336,21 +7303,6 @@ ir.cpp:
# 1036| params:
#-----| 0: [Parameter] p#0
#-----| Type = [RValueReferenceType] lambda [] type at line 1036, col. 21 &&
# 1036| initializations:
# 1036| 0: [ConstructorFieldInit] constructor init of field s
# 1036| Type = [SpecifiedType] const String
# 1036| ValueCategory = prvalue
# 1036| 0: [ConstructorCall] call to String
# 1036| Type = [VoidType] void
# 1036| ValueCategory = prvalue
# 1036| 1: [ConstructorFieldInit] constructor init of field x
# 1036| Type = [IntType] int
# 1036| ValueCategory = prvalue
# 1036| 0: [Literal] Unknown literal
# 1036| Type = [IntType] int
# 1036| ValueCategory = prvalue
# 1036| body: [Block] { ... }
# 1036| 0: [ReturnStmt] return ...
# 1036| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1036, col. 21)::(constructor)()
# 1036| params:
# 1036| [Destructor] void (void Lambda(int, String const&))::(lambda [] type at line 1036, col. 21)::~<unnamed>()
@@ -7403,15 +7355,6 @@ ir.cpp:
# 1038| params:
#-----| 0: [Parameter] p#0
#-----| Type = [RValueReferenceType] lambda [] type at line 1038, col. 30 &&
# 1038| initializations:
# 1038| 0: [ConstructorFieldInit] constructor init of field s
# 1038| Type = [LValueReferenceType] const String &
# 1038| ValueCategory = prvalue
# 1038| 0: [Literal] Unknown literal
# 1038| Type = [LValueReferenceType] const String &
# 1038| ValueCategory = prvalue
# 1038| body: [Block] { ... }
# 1038| 0: [ReturnStmt] return ...
# 1038| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1038, col. 30)::(constructor)()
# 1038| params:
# 1038| [ConstMemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1038, col. 30)::operator()(float) const
@@ -7451,15 +7394,6 @@ ir.cpp:
# 1040| params:
#-----| 0: [Parameter] p#0
#-----| Type = [RValueReferenceType] lambda [] type at line 1040, col. 30 &&
# 1040| initializations:
# 1040| 0: [ConstructorFieldInit] constructor init of field s
# 1040| Type = [SpecifiedType] const String
# 1040| ValueCategory = prvalue
# 1040| 0: [ConstructorCall] call to String
# 1040| Type = [VoidType] void
# 1040| ValueCategory = prvalue
# 1040| body: [Block] { ... }
# 1040| 0: [ReturnStmt] return ...
# 1040| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)()
# 1040| params:
# 1040| [Destructor] void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::~<unnamed>()
@@ -7510,21 +7444,6 @@ ir.cpp:
# 1042| params:
#-----| 0: [Parameter] p#0
#-----| Type = [RValueReferenceType] lambda [] type at line 1042, col. 32 &&
# 1042| initializations:
# 1042| 0: [ConstructorFieldInit] constructor init of field s
# 1042| Type = [LValueReferenceType] const String &
# 1042| ValueCategory = prvalue
# 1042| 0: [Literal] Unknown literal
# 1042| Type = [LValueReferenceType] const String &
# 1042| ValueCategory = prvalue
# 1042| 1: [ConstructorFieldInit] constructor init of field x
# 1042| Type = [IntType] int
# 1042| ValueCategory = prvalue
# 1042| 0: [Literal] Unknown literal
# 1042| Type = [IntType] int
# 1042| ValueCategory = prvalue
# 1042| body: [Block] { ... }
# 1042| 0: [ReturnStmt] return ...
# 1042| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1042, col. 32)::(constructor)()
# 1042| params:
# 1042| [ConstMemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1042, col. 32)::operator()(float) const
@@ -7566,33 +7485,6 @@ ir.cpp:
# 1045| params:
#-----| 0: [Parameter] p#0
#-----| Type = [RValueReferenceType] lambda [] type at line 1045, col. 23 &&
# 1045| initializations:
# 1045| 0: [ConstructorFieldInit] constructor init of field s
# 1045| Type = [LValueReferenceType] const String &
# 1045| ValueCategory = prvalue
# 1045| 0: [Literal] Unknown literal
# 1045| Type = [LValueReferenceType] const String &
# 1045| ValueCategory = prvalue
# 1045| 1: [ConstructorFieldInit] constructor init of field x
# 1045| Type = [IntType] int
# 1045| ValueCategory = prvalue
# 1045| 0: [Literal] Unknown literal
# 1045| Type = [IntType] int
# 1045| ValueCategory = prvalue
# 1045| 2: [ConstructorFieldInit] constructor init of field i
# 1045| Type = [IntType] int
# 1045| ValueCategory = prvalue
# 1045| 0: [Literal] Unknown literal
# 1045| Type = [IntType] int
# 1045| ValueCategory = prvalue
# 1045| 3: [ConstructorFieldInit] constructor init of field j
# 1045| Type = [LValueReferenceType] int &
# 1045| ValueCategory = prvalue
# 1045| 0: [Literal] Unknown literal
# 1045| Type = [LValueReferenceType] int &
# 1045| ValueCategory = prvalue
# 1045| body: [Block] { ... }
# 1045| 0: [ReturnStmt] return ...
# 1045| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1045, col. 23)::(constructor)()
# 1045| params:
# 1045| [ConstMemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1045, col. 23)::operator()(float) const

View File

@@ -0,0 +1 @@
semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSASanity.ql

View File

@@ -2700,65 +2700,60 @@ ir.cpp:
# 571| mu0_1(unknown) = AliasedDefinition :
# 571| mu0_2(unknown) = UnmodeledDefinition :
# 572| r0_3(glval<char[32]>) = VariableAddress[a_pad] :
# 572| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3
# 572| r0_5(glval<char[1]>) = StringConstant[""] :
# 572| r0_6(char[1]) = Load : &:r0_5, ~mu0_2
# 572| mu0_7(char[1]) = Store : &:r0_3, r0_6
# 572| r0_8(unknown[31]) = Constant[0] :
# 572| r0_9(int) = Constant[1] :
# 572| r0_10(glval<char>) = PointerAdd[1] : r0_3, r0_9
# 572| mu0_11(unknown[31]) = Store : &:r0_10, r0_8
# 573| r0_12(glval<char[4]>) = VariableAddress[a_nopad] :
# 573| r0_13(glval<char[4]>) = StringConstant["foo"] :
# 573| r0_14(char[4]) = Load : &:r0_13, ~mu0_2
# 573| mu0_15(char[4]) = Store : &:r0_12, r0_14
# 574| r0_16(glval<char[5]>) = VariableAddress[a_infer] :
# 574| r0_17(glval<char[5]>) = StringConstant["blah"] :
# 574| r0_18(char[5]) = Load : &:r0_17, ~mu0_2
# 574| mu0_19(char[5]) = Store : &:r0_16, r0_18
# 575| r0_20(glval<char[2]>) = VariableAddress[b] :
# 575| mu0_21(char[2]) = Uninitialized[b] : &:r0_20
# 576| r0_22(glval<char[2]>) = VariableAddress[c] :
# 576| mu0_23(char[2]) = Uninitialized[c] : &:r0_22
# 576| r0_24(int) = Constant[0] :
# 576| r0_25(glval<char>) = PointerAdd[1] : r0_22, r0_24
# 576| r0_26(unknown[2]) = Constant[0] :
# 576| mu0_27(unknown[2]) = Store : &:r0_25, r0_26
# 577| r0_28(glval<char[2]>) = VariableAddress[d] :
# 577| mu0_29(char[2]) = Uninitialized[d] : &:r0_28
# 577| r0_30(int) = Constant[0] :
# 577| r0_31(glval<char>) = PointerAdd[1] : r0_28, r0_30
# 577| r0_32(char) = Constant[0] :
# 577| mu0_33(char) = Store : &:r0_31, r0_32
# 577| r0_34(int) = Constant[1] :
# 577| r0_35(glval<char>) = PointerAdd[1] : r0_28, r0_34
# 577| r0_36(char) = Constant[0] :
# 577| mu0_37(char) = Store : &:r0_35, r0_36
# 578| r0_38(glval<char[2]>) = VariableAddress[e] :
# 578| mu0_39(char[2]) = Uninitialized[e] : &:r0_38
# 578| r0_40(int) = Constant[0] :
# 578| r0_41(glval<char>) = PointerAdd[1] : r0_38, r0_40
# 578| r0_42(char) = Constant[0] :
# 578| mu0_43(char) = Store : &:r0_41, r0_42
# 578| r0_44(int) = Constant[1] :
# 578| r0_45(glval<char>) = PointerAdd[1] : r0_38, r0_44
# 578| r0_46(char) = Constant[1] :
# 578| mu0_47(char) = Store : &:r0_45, r0_46
# 579| r0_48(glval<char[3]>) = VariableAddress[f] :
# 579| mu0_49(char[3]) = Uninitialized[f] : &:r0_48
# 579| r0_50(int) = Constant[0] :
# 579| r0_51(glval<char>) = PointerAdd[1] : r0_48, r0_50
# 579| r0_52(char) = Constant[0] :
# 579| mu0_53(char) = Store : &:r0_51, r0_52
# 579| r0_54(int) = Constant[1] :
# 579| r0_55(glval<char>) = PointerAdd[1] : r0_48, r0_54
# 579| r0_56(unknown[2]) = Constant[0] :
# 579| mu0_57(unknown[2]) = Store : &:r0_55, r0_56
# 580| v0_58(void) = NoOp :
# 571| v0_59(void) = ReturnVoid :
# 571| v0_60(void) = UnmodeledUse : mu*
# 571| v0_61(void) = AliasedUse : ~mu0_2
# 571| v0_62(void) = ExitFunction :
# 572| r0_4(glval<char[32]>) = StringConstant[""] :
# 572| r0_5(char[32]) = Load : &:r0_4, ~mu0_2
# 572| mu0_6(char[32]) = Store : &:r0_3, r0_5
# 573| r0_7(glval<char[4]>) = VariableAddress[a_nopad] :
# 573| r0_8(glval<char[4]>) = StringConstant["foo"] :
# 573| r0_9(char[4]) = Load : &:r0_8, ~mu0_2
# 573| mu0_10(char[4]) = Store : &:r0_7, r0_9
# 574| r0_11(glval<char[5]>) = VariableAddress[a_infer] :
# 574| r0_12(glval<char[5]>) = StringConstant["blah"] :
# 574| r0_13(char[5]) = Load : &:r0_12, ~mu0_2
# 574| mu0_14(char[5]) = Store : &:r0_11, r0_13
# 575| r0_15(glval<char[2]>) = VariableAddress[b] :
# 575| mu0_16(char[2]) = Uninitialized[b] : &:r0_15
# 576| r0_17(glval<char[2]>) = VariableAddress[c] :
# 576| mu0_18(char[2]) = Uninitialized[c] : &:r0_17
# 576| r0_19(int) = Constant[0] :
# 576| r0_20(glval<char>) = PointerAdd[1] : r0_17, r0_19
# 576| r0_21(unknown[2]) = Constant[0] :
# 576| mu0_22(unknown[2]) = Store : &:r0_20, r0_21
# 577| r0_23(glval<char[2]>) = VariableAddress[d] :
# 577| mu0_24(char[2]) = Uninitialized[d] : &:r0_23
# 577| r0_25(int) = Constant[0] :
# 577| r0_26(glval<char>) = PointerAdd[1] : r0_23, r0_25
# 577| r0_27(char) = Constant[0] :
# 577| mu0_28(char) = Store : &:r0_26, r0_27
# 577| r0_29(int) = Constant[1] :
# 577| r0_30(glval<char>) = PointerAdd[1] : r0_23, r0_29
# 577| r0_31(char) = Constant[0] :
# 577| mu0_32(char) = Store : &:r0_30, r0_31
# 578| r0_33(glval<char[2]>) = VariableAddress[e] :
# 578| mu0_34(char[2]) = Uninitialized[e] : &:r0_33
# 578| r0_35(int) = Constant[0] :
# 578| r0_36(glval<char>) = PointerAdd[1] : r0_33, r0_35
# 578| r0_37(char) = Constant[0] :
# 578| mu0_38(char) = Store : &:r0_36, r0_37
# 578| r0_39(int) = Constant[1] :
# 578| r0_40(glval<char>) = PointerAdd[1] : r0_33, r0_39
# 578| r0_41(char) = Constant[1] :
# 578| mu0_42(char) = Store : &:r0_40, r0_41
# 579| r0_43(glval<char[3]>) = VariableAddress[f] :
# 579| mu0_44(char[3]) = Uninitialized[f] : &:r0_43
# 579| r0_45(int) = Constant[0] :
# 579| r0_46(glval<char>) = PointerAdd[1] : r0_43, r0_45
# 579| r0_47(char) = Constant[0] :
# 579| mu0_48(char) = Store : &:r0_46, r0_47
# 579| r0_49(int) = Constant[1] :
# 579| r0_50(glval<char>) = PointerAdd[1] : r0_43, r0_49
# 579| r0_51(unknown[2]) = Constant[0] :
# 579| mu0_52(unknown[2]) = Store : &:r0_50, r0_51
# 580| v0_53(void) = NoOp :
# 571| v0_54(void) = ReturnVoid :
# 571| v0_55(void) = UnmodeledUse : mu*
# 571| v0_56(void) = AliasedUse : ~mu0_2
# 571| v0_57(void) = ExitFunction :
# 584| void VarArgs()
# 584| Block 0
@@ -4898,20 +4893,6 @@ ir.cpp:
# 1025| v0_8(void) = AliasedUse : ~mu0_2
# 1025| v0_9(void) = ExitFunction :
# 1029| void (lambda [] type at line 1029, col. 12)::(constructor)((lambda [] type at line 1029, col. 12)&&)
# 1029| Block 0
# 1029| v0_0(void) = EnterFunction :
# 1029| mu0_1(unknown) = AliasedDefinition :
# 1029| mu0_2(unknown) = UnmodeledDefinition :
# 1029| r0_3(glval<decltype([...](...){...})>) = InitializeThis :
#-----| r0_4(glval<lambda [] type at line 1029, col. 12 &&>) = VariableAddress[p#0] :
#-----| mu0_5(lambda [] type at line 1029, col. 12 &&) = InitializeParameter[p#0] : &:r0_4
# 1029| v0_6(void) = NoOp :
# 1029| v0_7(void) = ReturnVoid :
# 1029| v0_8(void) = UnmodeledUse : mu*
# 1029| v0_9(void) = AliasedUse : ~mu0_2
# 1029| v0_10(void) = ExitFunction :
# 1029| void (lambda [] type at line 1029, col. 12)::operator()() const
# 1029| Block 0
# 1029| v0_0(void) = EnterFunction :
@@ -4941,196 +4922,168 @@ ir.cpp:
# 1031| void Lambda(int, String const&)
# 1031| Block 0
# 1031| v0_0(void) = EnterFunction :
# 1031| mu0_1(unknown) = AliasedDefinition :
# 1031| mu0_2(unknown) = UnmodeledDefinition :
# 1031| r0_3(glval<int>) = VariableAddress[x] :
# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3
# 1031| r0_5(glval<String &>) = VariableAddress[s] :
# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5
# 1032| r0_7(glval<decltype([...](...){...})>) = VariableAddress[lambda_empty] :
# 1032| r0_8(glval<decltype([...](...){...})>) = VariableAddress[#temp1032:23] :
# 1032| mu0_9(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_8
# 1032| r0_10(decltype([...](...){...})) = Load : &:r0_8, ~mu0_2
# 1032| mu0_11(decltype([...](...){...})) = Store : &:r0_7, r0_10
# 1033| r0_12(char) = Constant[65] :
# 1034| r0_13(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref] :
# 1034| r0_14(glval<decltype([...](...){...})>) = VariableAddress[#temp1034:21] :
# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_14
# 1034| r0_16(glval<String &>) = FieldAddress[s] : r0_14
#-----| r0_17(glval<String &>) = VariableAddress[s] :
#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2
# 1034| r0_19(glval<String>) = CopyValue : r0_18
# 1034| r0_20(String &) = CopyValue : r0_19
# 1034| mu0_21(String &) = Store : &:r0_16, r0_20
# 1034| r0_22(glval<int &>) = FieldAddress[x] : r0_14
#-----| r0_23(glval<int>) = VariableAddress[x] :
#-----| r0_24(int &) = CopyValue : r0_23
#-----| mu0_25(int &) = Store : &:r0_22, r0_24
# 1034| r0_26(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2
# 1034| mu0_27(decltype([...](...){...})) = Store : &:r0_13, r0_26
# 1035| r0_28(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref] :
# 1035| r0_29(glval<decltype([...](...){...})>) = Convert : r0_28
# 1035| r0_30(glval<unknown>) = FunctionAddress[operator()] :
# 1035| r0_31(float) = Constant[1.0] :
# 1035| r0_32(char) = Call : func:r0_30, this:r0_29, 0:r0_31
# 1035| mu0_33(unknown) = ^CallSideEffect : ~mu0_2
# 1035| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_29, ~mu0_2
# 1035| mu0_35(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_29
# 1036| r0_36(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] :
# 1036| mu0_37(decltype([...](...){...})) = Uninitialized[lambda_val] : &:r0_36
# 1036| r0_38(glval<unknown>) = FunctionAddress[(constructor)] :
# 1036| r0_39(glval<decltype([...](...){...})>) = VariableAddress[#temp1036:21] :
# 1036| mu0_40(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_39
# 1036| r0_41(glval<String>) = FieldAddress[s] : r0_39
#-----| r0_42(glval<unknown>) = FunctionAddress[String] :
#-----| v0_43(void) = Call : func:r0_42, this:r0_41
#-----| mu0_44(unknown) = ^CallSideEffect : ~mu0_2
#-----| mu0_45(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_41
# 1036| r0_46(glval<int>) = FieldAddress[x] : r0_39
#-----| r0_47(glval<int>) = VariableAddress[x] :
#-----| r0_48(int) = Load : &:r0_47, ~mu0_2
#-----| mu0_49(int) = Store : &:r0_46, r0_48
# 1036| r0_50(decltype([...](...){...})) = Load : &:r0_39, ~mu0_2
# 1036| r0_51(lambda [] type at line 1036, col. 21 &) = CopyValue : r0_50
# 1036| v0_52(void) = Call : func:r0_38, this:r0_36, 0:r0_51
# 1036| mu0_53(unknown) = ^CallSideEffect : ~mu0_2
# 1036| mu0_54(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_36
# 1036| v0_55(void) = ^BufferReadSideEffect[0] : &:r0_51, ~mu0_2
# 1036| mu0_56(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_51
# 1037| r0_57(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] :
# 1037| r0_58(glval<decltype([...](...){...})>) = Convert : r0_57
# 1037| r0_59(glval<unknown>) = FunctionAddress[operator()] :
# 1037| r0_60(float) = Constant[2.0] :
# 1037| r0_61(char) = Call : func:r0_59, this:r0_58, 0:r0_60
# 1037| mu0_62(unknown) = ^CallSideEffect : ~mu0_2
# 1037| v0_63(void) = ^BufferReadSideEffect[-1] : &:r0_58, ~mu0_2
# 1037| mu0_64(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_58
# 1038| r0_65(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] :
# 1038| r0_66(glval<decltype([...](...){...})>) = VariableAddress[#temp1038:30] :
# 1038| mu0_67(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_66
# 1038| r0_68(glval<String &>) = FieldAddress[s] : r0_66
# 1038| r0_69(glval<String &>) = VariableAddress[s] :
# 1038| r0_70(String &) = Load : &:r0_69, ~mu0_2
# 1038| r0_71(glval<String>) = CopyValue : r0_70
# 1038| r0_72(String &) = CopyValue : r0_71
# 1038| mu0_73(String &) = Store : &:r0_68, r0_72
# 1038| r0_74(decltype([...](...){...})) = Load : &:r0_66, ~mu0_2
# 1038| mu0_75(decltype([...](...){...})) = Store : &:r0_65, r0_74
# 1039| r0_76(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] :
# 1039| r0_77(glval<decltype([...](...){...})>) = Convert : r0_76
# 1039| r0_78(glval<unknown>) = FunctionAddress[operator()] :
# 1039| r0_79(float) = Constant[3.0] :
# 1039| r0_80(char) = Call : func:r0_78, this:r0_77, 0:r0_79
# 1039| mu0_81(unknown) = ^CallSideEffect : ~mu0_2
# 1039| v0_82(void) = ^BufferReadSideEffect[-1] : &:r0_77, ~mu0_2
# 1039| mu0_83(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_77
# 1040| r0_84(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] :
# 1040| mu0_85(decltype([...](...){...})) = Uninitialized[lambda_val_explicit] : &:r0_84
# 1040| r0_86(glval<unknown>) = FunctionAddress[(constructor)] :
# 1040| r0_87(glval<decltype([...](...){...})>) = VariableAddress[#temp1040:30] :
# 1040| mu0_88(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_87
# 1040| r0_89(glval<String>) = FieldAddress[s] : r0_87
#-----| r0_90(glval<unknown>) = FunctionAddress[String] :
#-----| v0_91(void) = Call : func:r0_90, this:r0_89
#-----| mu0_92(unknown) = ^CallSideEffect : ~mu0_2
#-----| mu0_93(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_89
# 1040| r0_94(decltype([...](...){...})) = Load : &:r0_87, ~mu0_2
# 1040| r0_95(lambda [] type at line 1040, col. 30 &) = CopyValue : r0_94
# 1040| v0_96(void) = Call : func:r0_86, this:r0_84, 0:r0_95
# 1040| mu0_97(unknown) = ^CallSideEffect : ~mu0_2
# 1040| mu0_98(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_84
# 1040| v0_99(void) = ^BufferReadSideEffect[0] : &:r0_95, ~mu0_2
# 1040| mu0_100(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_95
# 1041| r0_101(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] :
# 1041| r0_102(glval<decltype([...](...){...})>) = Convert : r0_101
# 1041| r0_103(glval<unknown>) = FunctionAddress[operator()] :
# 1041| r0_104(float) = Constant[4.0] :
# 1041| r0_105(char) = Call : func:r0_103, this:r0_102, 0:r0_104
# 1041| mu0_106(unknown) = ^CallSideEffect : ~mu0_2
# 1041| v0_107(void) = ^BufferReadSideEffect[-1] : &:r0_102, ~mu0_2
# 1041| mu0_108(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_102
# 1042| r0_109(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] :
# 1042| r0_110(glval<decltype([...](...){...})>) = VariableAddress[#temp1042:32] :
# 1042| mu0_111(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_110
# 1042| r0_112(glval<String &>) = FieldAddress[s] : r0_110
# 1042| r0_113(glval<String &>) = VariableAddress[s] :
# 1042| r0_114(String &) = Load : &:r0_113, ~mu0_2
# 1042| r0_115(glval<String>) = CopyValue : r0_114
# 1042| r0_116(String &) = CopyValue : r0_115
# 1042| mu0_117(String &) = Store : &:r0_112, r0_116
# 1042| r0_118(glval<int>) = FieldAddress[x] : r0_110
# 1042| r0_119(glval<int>) = VariableAddress[x] :
# 1042| r0_120(int) = Load : &:r0_119, ~mu0_2
# 1042| mu0_121(int) = Store : &:r0_118, r0_120
# 1042| r0_122(decltype([...](...){...})) = Load : &:r0_110, ~mu0_2
# 1042| mu0_123(decltype([...](...){...})) = Store : &:r0_109, r0_122
# 1043| r0_124(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] :
# 1043| r0_125(glval<decltype([...](...){...})>) = Convert : r0_124
# 1043| r0_126(glval<unknown>) = FunctionAddress[operator()] :
# 1043| r0_127(float) = Constant[5.0] :
# 1043| r0_128(char) = Call : func:r0_126, this:r0_125, 0:r0_127
# 1043| mu0_129(unknown) = ^CallSideEffect : ~mu0_2
# 1043| v0_130(void) = ^BufferReadSideEffect[-1] : &:r0_125, ~mu0_2
# 1043| mu0_131(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_125
# 1044| r0_132(glval<int>) = VariableAddress[r] :
# 1044| r0_133(glval<int>) = VariableAddress[x] :
# 1044| r0_134(int) = Load : &:r0_133, ~mu0_2
# 1044| r0_135(int) = Constant[1] :
# 1044| r0_136(int) = Sub : r0_134, r0_135
# 1044| mu0_137(int) = Store : &:r0_132, r0_136
# 1045| r0_138(glval<decltype([...](...){...})>) = VariableAddress[lambda_inits] :
# 1045| r0_139(glval<decltype([...](...){...})>) = VariableAddress[#temp1045:23] :
# 1045| mu0_140(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_139
# 1045| r0_141(glval<String &>) = FieldAddress[s] : r0_139
# 1045| r0_142(glval<String &>) = VariableAddress[s] :
# 1045| r0_143(String &) = Load : &:r0_142, ~mu0_2
# 1045| r0_144(glval<String>) = CopyValue : r0_143
# 1045| r0_145(String &) = CopyValue : r0_144
# 1045| mu0_146(String &) = Store : &:r0_141, r0_145
# 1045| r0_147(glval<int>) = FieldAddress[x] : r0_139
# 1045| r0_148(glval<int>) = VariableAddress[x] :
# 1045| r0_149(int) = Load : &:r0_148, ~mu0_2
# 1045| mu0_150(int) = Store : &:r0_147, r0_149
# 1045| r0_151(glval<int>) = FieldAddress[i] : r0_139
# 1045| r0_152(glval<int>) = VariableAddress[x] :
# 1045| r0_153(int) = Load : &:r0_152, ~mu0_2
# 1045| r0_154(int) = Constant[1] :
# 1045| r0_155(int) = Add : r0_153, r0_154
# 1045| mu0_156(int) = Store : &:r0_151, r0_155
# 1045| r0_157(glval<int &>) = FieldAddress[j] : r0_139
# 1045| r0_158(glval<int>) = VariableAddress[r] :
# 1045| r0_159(int &) = CopyValue : r0_158
# 1045| mu0_160(int &) = Store : &:r0_157, r0_159
# 1045| r0_161(decltype([...](...){...})) = Load : &:r0_139, ~mu0_2
# 1045| mu0_162(decltype([...](...){...})) = Store : &:r0_138, r0_161
# 1046| r0_163(glval<decltype([...](...){...})>) = VariableAddress[lambda_inits] :
# 1046| r0_164(glval<decltype([...](...){...})>) = Convert : r0_163
# 1046| r0_165(glval<unknown>) = FunctionAddress[operator()] :
# 1046| r0_166(float) = Constant[6.0] :
# 1046| r0_167(char) = Call : func:r0_165, this:r0_164, 0:r0_166
# 1046| mu0_168(unknown) = ^CallSideEffect : ~mu0_2
# 1046| v0_169(void) = ^BufferReadSideEffect[-1] : &:r0_164, ~mu0_2
# 1046| mu0_170(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_164
# 1047| v0_171(void) = NoOp :
# 1031| v0_172(void) = ReturnVoid :
# 1031| v0_173(void) = UnmodeledUse : mu*
# 1031| v0_174(void) = AliasedUse : ~mu0_2
# 1031| v0_175(void) = ExitFunction :
# 1032| void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)&&)
# 1032| Block 0
# 1032| v0_0(void) = EnterFunction :
# 1032| mu0_1(unknown) = AliasedDefinition :
# 1032| mu0_2(unknown) = UnmodeledDefinition :
# 1032| r0_3(glval<decltype([...](...){...})>) = InitializeThis :
#-----| r0_4(glval<lambda [] type at line 1032, col. 23 &&>) = VariableAddress[p#0] :
#-----| mu0_5(lambda [] type at line 1032, col. 23 &&) = InitializeParameter[p#0] : &:r0_4
# 1032| v0_6(void) = NoOp :
# 1032| v0_7(void) = ReturnVoid :
# 1032| v0_8(void) = UnmodeledUse : mu*
# 1032| v0_9(void) = AliasedUse : ~mu0_2
# 1032| v0_10(void) = ExitFunction :
# 1031| v0_0(void) = EnterFunction :
# 1031| mu0_1(unknown) = AliasedDefinition :
# 1031| mu0_2(unknown) = UnmodeledDefinition :
# 1031| r0_3(glval<int>) = VariableAddress[x] :
# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3
# 1031| r0_5(glval<String &>) = VariableAddress[s] :
# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5
# 1032| r0_7(glval<decltype([...](...){...})>) = VariableAddress[lambda_empty] :
# 1032| r0_8(glval<decltype([...](...){...})>) = VariableAddress[#temp1032:23] :
# 1032| mu0_9(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_8
# 1032| r0_10(decltype([...](...){...})) = Load : &:r0_8, ~mu0_2
# 1032| mu0_11(decltype([...](...){...})) = Store : &:r0_7, r0_10
# 1033| r0_12(char) = Constant[65] :
# 1034| r0_13(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref] :
# 1034| r0_14(glval<decltype([...](...){...})>) = VariableAddress[#temp1034:20] :
# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:20] : &:r0_14
# 1034| r0_16(glval<String &>) = FieldAddress[s] : r0_14
#-----| r0_17(glval<String &>) = VariableAddress[s] :
#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2
# 1034| r0_19(glval<String>) = CopyValue : r0_18
# 1034| r0_20(String &) = CopyValue : r0_19
# 1034| mu0_21(String &) = Store : &:r0_16, r0_20
# 1034| r0_22(glval<int &>) = FieldAddress[x] : r0_14
#-----| r0_23(glval<int>) = VariableAddress[x] :
#-----| r0_24(int &) = CopyValue : r0_23
#-----| mu0_25(int &) = Store : &:r0_22, r0_24
# 1034| r0_26(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2
# 1034| mu0_27(decltype([...](...){...})) = Store : &:r0_13, r0_26
# 1035| r0_28(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref] :
# 1035| r0_29(glval<decltype([...](...){...})>) = Convert : r0_28
# 1035| r0_30(glval<unknown>) = FunctionAddress[operator()] :
# 1035| r0_31(float) = Constant[1.0] :
# 1035| r0_32(char) = Call : func:r0_30, this:r0_29, 0:r0_31
# 1035| mu0_33(unknown) = ^CallSideEffect : ~mu0_2
# 1035| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_29, ~mu0_2
# 1035| mu0_35(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_29
# 1036| r0_36(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] :
# 1036| r0_37(glval<decltype([...](...){...})>) = VariableAddress[#temp1036:20] :
# 1036| mu0_38(decltype([...](...){...})) = Uninitialized[#temp1036:20] : &:r0_37
# 1036| r0_39(glval<String>) = FieldAddress[s] : r0_37
#-----| r0_40(glval<unknown>) = FunctionAddress[String] :
#-----| v0_41(void) = Call : func:r0_40, this:r0_39
#-----| mu0_42(unknown) = ^CallSideEffect : ~mu0_2
#-----| mu0_43(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_39
# 1036| r0_44(glval<int>) = FieldAddress[x] : r0_37
#-----| r0_45(glval<int>) = VariableAddress[x] :
#-----| r0_46(int) = Load : &:r0_45, ~mu0_2
#-----| mu0_47(int) = Store : &:r0_44, r0_46
# 1036| r0_48(decltype([...](...){...})) = Load : &:r0_37, ~mu0_2
# 1036| mu0_49(decltype([...](...){...})) = Store : &:r0_36, r0_48
# 1037| r0_50(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] :
# 1037| r0_51(glval<decltype([...](...){...})>) = Convert : r0_50
# 1037| r0_52(glval<unknown>) = FunctionAddress[operator()] :
# 1037| r0_53(float) = Constant[2.0] :
# 1037| r0_54(char) = Call : func:r0_52, this:r0_51, 0:r0_53
# 1037| mu0_55(unknown) = ^CallSideEffect : ~mu0_2
# 1037| v0_56(void) = ^BufferReadSideEffect[-1] : &:r0_51, ~mu0_2
# 1037| mu0_57(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_51
# 1038| r0_58(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] :
# 1038| r0_59(glval<decltype([...](...){...})>) = VariableAddress[#temp1038:29] :
# 1038| mu0_60(decltype([...](...){...})) = Uninitialized[#temp1038:29] : &:r0_59
# 1038| r0_61(glval<String &>) = FieldAddress[s] : r0_59
# 1038| r0_62(glval<String &>) = VariableAddress[s] :
# 1038| r0_63(String &) = Load : &:r0_62, ~mu0_2
# 1038| r0_64(glval<String>) = CopyValue : r0_63
# 1038| r0_65(String &) = CopyValue : r0_64
# 1038| mu0_66(String &) = Store : &:r0_61, r0_65
# 1038| r0_67(decltype([...](...){...})) = Load : &:r0_59, ~mu0_2
# 1038| mu0_68(decltype([...](...){...})) = Store : &:r0_58, r0_67
# 1039| r0_69(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] :
# 1039| r0_70(glval<decltype([...](...){...})>) = Convert : r0_69
# 1039| r0_71(glval<unknown>) = FunctionAddress[operator()] :
# 1039| r0_72(float) = Constant[3.0] :
# 1039| r0_73(char) = Call : func:r0_71, this:r0_70, 0:r0_72
# 1039| mu0_74(unknown) = ^CallSideEffect : ~mu0_2
# 1039| v0_75(void) = ^BufferReadSideEffect[-1] : &:r0_70, ~mu0_2
# 1039| mu0_76(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_70
# 1040| r0_77(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] :
# 1040| r0_78(glval<decltype([...](...){...})>) = VariableAddress[#temp1040:29] :
# 1040| mu0_79(decltype([...](...){...})) = Uninitialized[#temp1040:29] : &:r0_78
# 1040| r0_80(glval<String>) = FieldAddress[s] : r0_78
#-----| r0_81(glval<unknown>) = FunctionAddress[String] :
#-----| v0_82(void) = Call : func:r0_81, this:r0_80
#-----| mu0_83(unknown) = ^CallSideEffect : ~mu0_2
#-----| mu0_84(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_80
# 1040| r0_85(decltype([...](...){...})) = Load : &:r0_78, ~mu0_2
# 1040| mu0_86(decltype([...](...){...})) = Store : &:r0_77, r0_85
# 1041| r0_87(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] :
# 1041| r0_88(glval<decltype([...](...){...})>) = Convert : r0_87
# 1041| r0_89(glval<unknown>) = FunctionAddress[operator()] :
# 1041| r0_90(float) = Constant[4.0] :
# 1041| r0_91(char) = Call : func:r0_89, this:r0_88, 0:r0_90
# 1041| mu0_92(unknown) = ^CallSideEffect : ~mu0_2
# 1041| v0_93(void) = ^BufferReadSideEffect[-1] : &:r0_88, ~mu0_2
# 1041| mu0_94(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_88
# 1042| r0_95(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] :
# 1042| r0_96(glval<decltype([...](...){...})>) = VariableAddress[#temp1042:31] :
# 1042| mu0_97(decltype([...](...){...})) = Uninitialized[#temp1042:31] : &:r0_96
# 1042| r0_98(glval<String &>) = FieldAddress[s] : r0_96
# 1042| r0_99(glval<String &>) = VariableAddress[s] :
# 1042| r0_100(String &) = Load : &:r0_99, ~mu0_2
# 1042| r0_101(glval<String>) = CopyValue : r0_100
# 1042| r0_102(String &) = CopyValue : r0_101
# 1042| mu0_103(String &) = Store : &:r0_98, r0_102
# 1042| r0_104(glval<int>) = FieldAddress[x] : r0_96
# 1042| r0_105(glval<int>) = VariableAddress[x] :
# 1042| r0_106(int) = Load : &:r0_105, ~mu0_2
# 1042| mu0_107(int) = Store : &:r0_104, r0_106
# 1042| r0_108(decltype([...](...){...})) = Load : &:r0_96, ~mu0_2
# 1042| mu0_109(decltype([...](...){...})) = Store : &:r0_95, r0_108
# 1043| r0_110(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] :
# 1043| r0_111(glval<decltype([...](...){...})>) = Convert : r0_110
# 1043| r0_112(glval<unknown>) = FunctionAddress[operator()] :
# 1043| r0_113(float) = Constant[5.0] :
# 1043| r0_114(char) = Call : func:r0_112, this:r0_111, 0:r0_113
# 1043| mu0_115(unknown) = ^CallSideEffect : ~mu0_2
# 1043| v0_116(void) = ^BufferReadSideEffect[-1] : &:r0_111, ~mu0_2
# 1043| mu0_117(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_111
# 1044| r0_118(glval<int>) = VariableAddress[r] :
# 1044| r0_119(glval<int>) = VariableAddress[x] :
# 1044| r0_120(int) = Load : &:r0_119, ~mu0_2
# 1044| r0_121(int) = Constant[1] :
# 1044| r0_122(int) = Sub : r0_120, r0_121
# 1044| mu0_123(int) = Store : &:r0_118, r0_122
# 1045| r0_124(glval<decltype([...](...){...})>) = VariableAddress[lambda_inits] :
# 1045| r0_125(glval<decltype([...](...){...})>) = VariableAddress[#temp1045:22] :
# 1045| mu0_126(decltype([...](...){...})) = Uninitialized[#temp1045:22] : &:r0_125
# 1045| r0_127(glval<String &>) = FieldAddress[s] : r0_125
# 1045| r0_128(glval<String &>) = VariableAddress[s] :
# 1045| r0_129(String &) = Load : &:r0_128, ~mu0_2
# 1045| r0_130(glval<String>) = CopyValue : r0_129
# 1045| r0_131(String &) = CopyValue : r0_130
# 1045| mu0_132(String &) = Store : &:r0_127, r0_131
# 1045| r0_133(glval<int>) = FieldAddress[x] : r0_125
# 1045| r0_134(glval<int>) = VariableAddress[x] :
# 1045| r0_135(int) = Load : &:r0_134, ~mu0_2
# 1045| mu0_136(int) = Store : &:r0_133, r0_135
# 1045| r0_137(glval<int>) = FieldAddress[i] : r0_125
# 1045| r0_138(glval<int>) = VariableAddress[x] :
# 1045| r0_139(int) = Load : &:r0_138, ~mu0_2
# 1045| r0_140(int) = Constant[1] :
# 1045| r0_141(int) = Add : r0_139, r0_140
# 1045| mu0_142(int) = Store : &:r0_137, r0_141
# 1045| r0_143(glval<int &>) = FieldAddress[j] : r0_125
# 1045| r0_144(glval<int>) = VariableAddress[r] :
# 1045| r0_145(int &) = CopyValue : r0_144
# 1045| mu0_146(int &) = Store : &:r0_143, r0_145
# 1045| r0_147(decltype([...](...){...})) = Load : &:r0_125, ~mu0_2
# 1045| mu0_148(decltype([...](...){...})) = Store : &:r0_124, r0_147
# 1046| r0_149(glval<decltype([...](...){...})>) = VariableAddress[lambda_inits] :
# 1046| r0_150(glval<decltype([...](...){...})>) = Convert : r0_149
# 1046| r0_151(glval<unknown>) = FunctionAddress[operator()] :
# 1046| r0_152(float) = Constant[6.0] :
# 1046| r0_153(char) = Call : func:r0_151, this:r0_150, 0:r0_152
# 1046| mu0_154(unknown) = ^CallSideEffect : ~mu0_2
# 1046| v0_155(void) = ^BufferReadSideEffect[-1] : &:r0_150, ~mu0_2
# 1046| mu0_156(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_150
# 1047| v0_157(void) = NoOp :
# 1031| v0_158(void) = ReturnVoid :
# 1031| v0_159(void) = UnmodeledUse : mu*
# 1031| v0_160(void) = AliasedUse : ~mu0_2
# 1031| v0_161(void) = ExitFunction :
# 1032| char (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::operator()(float) const
# 1032| Block 0
@@ -5267,25 +5220,6 @@ ir.cpp:
# 1038| v0_23(void) = AliasedUse : ~mu0_2
# 1038| v0_24(void) = ExitFunction :
# 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&)
# 1040| Block 0
# 1040| v0_0(void) = EnterFunction :
# 1040| mu0_1(unknown) = AliasedDefinition :
# 1040| mu0_2(unknown) = UnmodeledDefinition :
# 1040| r0_3(glval<decltype([...](...){...})>) = InitializeThis :
#-----| r0_4(glval<lambda [] type at line 1040, col. 30 &&>) = VariableAddress[p#0] :
#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4
# 1040| r0_6(glval<String>) = FieldAddress[s] : r0_3
# 1040| r0_7(glval<unknown>) = FunctionAddress[String] :
# 1040| v0_8(void) = Call : func:r0_7, this:r0_6
# 1040| mu0_9(unknown) = ^CallSideEffect : ~mu0_2
# 1040| mu0_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_6
# 1040| v0_11(void) = NoOp :
# 1040| v0_12(void) = ReturnVoid :
# 1040| v0_13(void) = UnmodeledUse : mu*
# 1040| v0_14(void) = AliasedUse : ~mu0_2
# 1040| v0_15(void) = ExitFunction :
# 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::~<unnamed>()
# 1040| Block 0
# 1040| v0_0(void) = EnterFunction :

View File

@@ -0,0 +1 @@
semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSASanity.ql

View File

@@ -884,73 +884,66 @@ ssa.cpp:
# 213| m0_1(unknown) = AliasedDefinition :
# 213| mu0_2(unknown) = UnmodeledDefinition :
# 214| r0_3(glval<char[32]>) = VariableAddress[a_pad] :
# 214| m0_4(char[32]) = Uninitialized[a_pad] : &:r0_3
# 214| r0_5(glval<char[1]>) = StringConstant[""] :
# 214| r0_6(char[1]) = Load : &:r0_5, ~m0_1
# 214| m0_7(char[1]) = Store : &:r0_3, r0_6
# 214| m0_8(char[32]) = Chi : total:m0_4, partial:m0_7
# 214| r0_9(unknown[31]) = Constant[0] :
# 214| r0_10(int) = Constant[1] :
# 214| r0_11(glval<char>) = PointerAdd[1] : r0_3, r0_10
# 214| m0_12(unknown[31]) = Store : &:r0_11, r0_9
# 214| m0_13(char[32]) = Chi : total:m0_8, partial:m0_12
# 215| r0_14(glval<char[4]>) = VariableAddress[a_nopad] :
# 215| r0_15(glval<char[4]>) = StringConstant["foo"] :
# 215| r0_16(char[4]) = Load : &:r0_15, ~m0_1
# 215| m0_17(char[4]) = Store : &:r0_14, r0_16
# 216| r0_18(glval<char[5]>) = VariableAddress[a_infer] :
# 216| r0_19(glval<char[5]>) = StringConstant["blah"] :
# 216| r0_20(char[5]) = Load : &:r0_19, ~m0_1
# 216| m0_21(char[5]) = Store : &:r0_18, r0_20
# 217| r0_22(glval<char[2]>) = VariableAddress[b] :
# 217| m0_23(char[2]) = Uninitialized[b] : &:r0_22
# 218| r0_24(glval<char[2]>) = VariableAddress[c] :
# 218| m0_25(char[2]) = Uninitialized[c] : &:r0_24
# 218| r0_26(int) = Constant[0] :
# 218| r0_27(glval<char>) = PointerAdd[1] : r0_24, r0_26
# 218| r0_28(unknown[2]) = Constant[0] :
# 218| m0_29(unknown[2]) = Store : &:r0_27, r0_28
# 219| r0_30(glval<char[2]>) = VariableAddress[d] :
# 219| m0_31(char[2]) = Uninitialized[d] : &:r0_30
# 219| r0_32(int) = Constant[0] :
# 219| r0_33(glval<char>) = PointerAdd[1] : r0_30, r0_32
# 219| r0_34(char) = Constant[0] :
# 219| m0_35(char) = Store : &:r0_33, r0_34
# 219| m0_36(char[2]) = Chi : total:m0_31, partial:m0_35
# 219| r0_37(int) = Constant[1] :
# 219| r0_38(glval<char>) = PointerAdd[1] : r0_30, r0_37
# 219| r0_39(char) = Constant[0] :
# 219| m0_40(char) = Store : &:r0_38, r0_39
# 219| m0_41(char[2]) = Chi : total:m0_36, partial:m0_40
# 220| r0_42(glval<char[2]>) = VariableAddress[e] :
# 220| m0_43(char[2]) = Uninitialized[e] : &:r0_42
# 220| r0_44(int) = Constant[0] :
# 220| r0_45(glval<char>) = PointerAdd[1] : r0_42, r0_44
# 220| r0_46(char) = Constant[0] :
# 220| m0_47(char) = Store : &:r0_45, r0_46
# 220| m0_48(char[2]) = Chi : total:m0_43, partial:m0_47
# 220| r0_49(int) = Constant[1] :
# 220| r0_50(glval<char>) = PointerAdd[1] : r0_42, r0_49
# 220| r0_51(char) = Constant[1] :
# 220| m0_52(char) = Store : &:r0_50, r0_51
# 220| m0_53(char[2]) = Chi : total:m0_48, partial:m0_52
# 221| r0_54(glval<char[3]>) = VariableAddress[f] :
# 221| m0_55(char[3]) = Uninitialized[f] : &:r0_54
# 221| r0_56(int) = Constant[0] :
# 221| r0_57(glval<char>) = PointerAdd[1] : r0_54, r0_56
# 221| r0_58(char) = Constant[0] :
# 221| m0_59(char) = Store : &:r0_57, r0_58
# 221| m0_60(char[3]) = Chi : total:m0_55, partial:m0_59
# 221| r0_61(int) = Constant[1] :
# 221| r0_62(glval<char>) = PointerAdd[1] : r0_54, r0_61
# 221| r0_63(unknown[2]) = Constant[0] :
# 221| m0_64(unknown[2]) = Store : &:r0_62, r0_63
# 221| m0_65(char[3]) = Chi : total:m0_60, partial:m0_64
# 222| v0_66(void) = NoOp :
# 213| v0_67(void) = ReturnVoid :
# 213| v0_68(void) = UnmodeledUse : mu*
# 213| v0_69(void) = AliasedUse : ~m0_1
# 213| v0_70(void) = ExitFunction :
# 214| r0_4(glval<char[32]>) = StringConstant[""] :
# 214| r0_5(char[32]) = Load : &:r0_4, ~m0_1
# 214| m0_6(char[32]) = Store : &:r0_3, r0_5
# 215| r0_7(glval<char[4]>) = VariableAddress[a_nopad] :
# 215| r0_8(glval<char[4]>) = StringConstant["foo"] :
# 215| r0_9(char[4]) = Load : &:r0_8, ~m0_1
# 215| m0_10(char[4]) = Store : &:r0_7, r0_9
# 216| r0_11(glval<char[5]>) = VariableAddress[a_infer] :
# 216| r0_12(glval<char[5]>) = StringConstant["blah"] :
# 216| r0_13(char[5]) = Load : &:r0_12, ~m0_1
# 216| m0_14(char[5]) = Store : &:r0_11, r0_13
# 217| r0_15(glval<char[2]>) = VariableAddress[b] :
# 217| m0_16(char[2]) = Uninitialized[b] : &:r0_15
# 218| r0_17(glval<char[2]>) = VariableAddress[c] :
# 218| m0_18(char[2]) = Uninitialized[c] : &:r0_17
# 218| r0_19(int) = Constant[0] :
# 218| r0_20(glval<char>) = PointerAdd[1] : r0_17, r0_19
# 218| r0_21(unknown[2]) = Constant[0] :
# 218| m0_22(unknown[2]) = Store : &:r0_20, r0_21
# 219| r0_23(glval<char[2]>) = VariableAddress[d] :
# 219| m0_24(char[2]) = Uninitialized[d] : &:r0_23
# 219| r0_25(int) = Constant[0] :
# 219| r0_26(glval<char>) = PointerAdd[1] : r0_23, r0_25
# 219| r0_27(char) = Constant[0] :
# 219| m0_28(char) = Store : &:r0_26, r0_27
# 219| m0_29(char[2]) = Chi : total:m0_24, partial:m0_28
# 219| r0_30(int) = Constant[1] :
# 219| r0_31(glval<char>) = PointerAdd[1] : r0_23, r0_30
# 219| r0_32(char) = Constant[0] :
# 219| m0_33(char) = Store : &:r0_31, r0_32
# 219| m0_34(char[2]) = Chi : total:m0_29, partial:m0_33
# 220| r0_35(glval<char[2]>) = VariableAddress[e] :
# 220| m0_36(char[2]) = Uninitialized[e] : &:r0_35
# 220| r0_37(int) = Constant[0] :
# 220| r0_38(glval<char>) = PointerAdd[1] : r0_35, r0_37
# 220| r0_39(char) = Constant[0] :
# 220| m0_40(char) = Store : &:r0_38, r0_39
# 220| m0_41(char[2]) = Chi : total:m0_36, partial:m0_40
# 220| r0_42(int) = Constant[1] :
# 220| r0_43(glval<char>) = PointerAdd[1] : r0_35, r0_42
# 220| r0_44(char) = Constant[1] :
# 220| m0_45(char) = Store : &:r0_43, r0_44
# 220| m0_46(char[2]) = Chi : total:m0_41, partial:m0_45
# 221| r0_47(glval<char[3]>) = VariableAddress[f] :
# 221| m0_48(char[3]) = Uninitialized[f] : &:r0_47
# 221| r0_49(int) = Constant[0] :
# 221| r0_50(glval<char>) = PointerAdd[1] : r0_47, r0_49
# 221| r0_51(char) = Constant[0] :
# 221| m0_52(char) = Store : &:r0_50, r0_51
# 221| m0_53(char[3]) = Chi : total:m0_48, partial:m0_52
# 221| r0_54(int) = Constant[1] :
# 221| r0_55(glval<char>) = PointerAdd[1] : r0_47, r0_54
# 221| r0_56(unknown[2]) = Constant[0] :
# 221| m0_57(unknown[2]) = Store : &:r0_55, r0_56
# 221| m0_58(char[3]) = Chi : total:m0_53, partial:m0_57
# 222| v0_59(void) = NoOp :
# 213| v0_60(void) = ReturnVoid :
# 213| v0_61(void) = UnmodeledUse : mu*
# 213| v0_62(void) = AliasedUse : ~m0_1
# 213| v0_63(void) = ExitFunction :
# 226| char StringLiteralAliasing()
# 226| Block 0

View File

@@ -0,0 +1 @@
semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSASanity.ql

View File

@@ -848,65 +848,60 @@ ssa.cpp:
# 213| mu0_1(unknown) = AliasedDefinition :
# 213| mu0_2(unknown) = UnmodeledDefinition :
# 214| r0_3(glval<char[32]>) = VariableAddress[a_pad] :
# 214| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3
# 214| r0_5(glval<char[1]>) = StringConstant[""] :
# 214| r0_6(char[1]) = Load : &:r0_5, ~mu0_2
# 214| mu0_7(char[1]) = Store : &:r0_3, r0_6
# 214| r0_8(unknown[31]) = Constant[0] :
# 214| r0_9(int) = Constant[1] :
# 214| r0_10(glval<char>) = PointerAdd[1] : r0_3, r0_9
# 214| mu0_11(unknown[31]) = Store : &:r0_10, r0_8
# 215| r0_12(glval<char[4]>) = VariableAddress[a_nopad] :
# 215| r0_13(glval<char[4]>) = StringConstant["foo"] :
# 215| r0_14(char[4]) = Load : &:r0_13, ~mu0_2
# 215| m0_15(char[4]) = Store : &:r0_12, r0_14
# 216| r0_16(glval<char[5]>) = VariableAddress[a_infer] :
# 216| r0_17(glval<char[5]>) = StringConstant["blah"] :
# 216| r0_18(char[5]) = Load : &:r0_17, ~mu0_2
# 216| m0_19(char[5]) = Store : &:r0_16, r0_18
# 217| r0_20(glval<char[2]>) = VariableAddress[b] :
# 217| m0_21(char[2]) = Uninitialized[b] : &:r0_20
# 218| r0_22(glval<char[2]>) = VariableAddress[c] :
# 218| mu0_23(char[2]) = Uninitialized[c] : &:r0_22
# 218| r0_24(int) = Constant[0] :
# 218| r0_25(glval<char>) = PointerAdd[1] : r0_22, r0_24
# 218| r0_26(unknown[2]) = Constant[0] :
# 218| mu0_27(unknown[2]) = Store : &:r0_25, r0_26
# 219| r0_28(glval<char[2]>) = VariableAddress[d] :
# 219| mu0_29(char[2]) = Uninitialized[d] : &:r0_28
# 219| r0_30(int) = Constant[0] :
# 219| r0_31(glval<char>) = PointerAdd[1] : r0_28, r0_30
# 219| r0_32(char) = Constant[0] :
# 219| mu0_33(char) = Store : &:r0_31, r0_32
# 219| r0_34(int) = Constant[1] :
# 219| r0_35(glval<char>) = PointerAdd[1] : r0_28, r0_34
# 219| r0_36(char) = Constant[0] :
# 219| mu0_37(char) = Store : &:r0_35, r0_36
# 220| r0_38(glval<char[2]>) = VariableAddress[e] :
# 220| mu0_39(char[2]) = Uninitialized[e] : &:r0_38
# 220| r0_40(int) = Constant[0] :
# 220| r0_41(glval<char>) = PointerAdd[1] : r0_38, r0_40
# 220| r0_42(char) = Constant[0] :
# 220| mu0_43(char) = Store : &:r0_41, r0_42
# 220| r0_44(int) = Constant[1] :
# 220| r0_45(glval<char>) = PointerAdd[1] : r0_38, r0_44
# 220| r0_46(char) = Constant[1] :
# 220| mu0_47(char) = Store : &:r0_45, r0_46
# 221| r0_48(glval<char[3]>) = VariableAddress[f] :
# 221| mu0_49(char[3]) = Uninitialized[f] : &:r0_48
# 221| r0_50(int) = Constant[0] :
# 221| r0_51(glval<char>) = PointerAdd[1] : r0_48, r0_50
# 221| r0_52(char) = Constant[0] :
# 221| mu0_53(char) = Store : &:r0_51, r0_52
# 221| r0_54(int) = Constant[1] :
# 221| r0_55(glval<char>) = PointerAdd[1] : r0_48, r0_54
# 221| r0_56(unknown[2]) = Constant[0] :
# 221| mu0_57(unknown[2]) = Store : &:r0_55, r0_56
# 222| v0_58(void) = NoOp :
# 213| v0_59(void) = ReturnVoid :
# 213| v0_60(void) = UnmodeledUse : mu*
# 213| v0_61(void) = AliasedUse : ~mu0_2
# 213| v0_62(void) = ExitFunction :
# 214| r0_4(glval<char[32]>) = StringConstant[""] :
# 214| r0_5(char[32]) = Load : &:r0_4, ~mu0_2
# 214| m0_6(char[32]) = Store : &:r0_3, r0_5
# 215| r0_7(glval<char[4]>) = VariableAddress[a_nopad] :
# 215| r0_8(glval<char[4]>) = StringConstant["foo"] :
# 215| r0_9(char[4]) = Load : &:r0_8, ~mu0_2
# 215| m0_10(char[4]) = Store : &:r0_7, r0_9
# 216| r0_11(glval<char[5]>) = VariableAddress[a_infer] :
# 216| r0_12(glval<char[5]>) = StringConstant["blah"] :
# 216| r0_13(char[5]) = Load : &:r0_12, ~mu0_2
# 216| m0_14(char[5]) = Store : &:r0_11, r0_13
# 217| r0_15(glval<char[2]>) = VariableAddress[b] :
# 217| m0_16(char[2]) = Uninitialized[b] : &:r0_15
# 218| r0_17(glval<char[2]>) = VariableAddress[c] :
# 218| mu0_18(char[2]) = Uninitialized[c] : &:r0_17
# 218| r0_19(int) = Constant[0] :
# 218| r0_20(glval<char>) = PointerAdd[1] : r0_17, r0_19
# 218| r0_21(unknown[2]) = Constant[0] :
# 218| mu0_22(unknown[2]) = Store : &:r0_20, r0_21
# 219| r0_23(glval<char[2]>) = VariableAddress[d] :
# 219| mu0_24(char[2]) = Uninitialized[d] : &:r0_23
# 219| r0_25(int) = Constant[0] :
# 219| r0_26(glval<char>) = PointerAdd[1] : r0_23, r0_25
# 219| r0_27(char) = Constant[0] :
# 219| mu0_28(char) = Store : &:r0_26, r0_27
# 219| r0_29(int) = Constant[1] :
# 219| r0_30(glval<char>) = PointerAdd[1] : r0_23, r0_29
# 219| r0_31(char) = Constant[0] :
# 219| mu0_32(char) = Store : &:r0_30, r0_31
# 220| r0_33(glval<char[2]>) = VariableAddress[e] :
# 220| mu0_34(char[2]) = Uninitialized[e] : &:r0_33
# 220| r0_35(int) = Constant[0] :
# 220| r0_36(glval<char>) = PointerAdd[1] : r0_33, r0_35
# 220| r0_37(char) = Constant[0] :
# 220| mu0_38(char) = Store : &:r0_36, r0_37
# 220| r0_39(int) = Constant[1] :
# 220| r0_40(glval<char>) = PointerAdd[1] : r0_33, r0_39
# 220| r0_41(char) = Constant[1] :
# 220| mu0_42(char) = Store : &:r0_40, r0_41
# 221| r0_43(glval<char[3]>) = VariableAddress[f] :
# 221| mu0_44(char[3]) = Uninitialized[f] : &:r0_43
# 221| r0_45(int) = Constant[0] :
# 221| r0_46(glval<char>) = PointerAdd[1] : r0_43, r0_45
# 221| r0_47(char) = Constant[0] :
# 221| mu0_48(char) = Store : &:r0_46, r0_47
# 221| r0_49(int) = Constant[1] :
# 221| r0_50(glval<char>) = PointerAdd[1] : r0_43, r0_49
# 221| r0_51(unknown[2]) = Constant[0] :
# 221| mu0_52(unknown[2]) = Store : &:r0_50, r0_51
# 222| v0_53(void) = NoOp :
# 213| v0_54(void) = ReturnVoid :
# 213| v0_55(void) = UnmodeledUse : mu*
# 213| v0_56(void) = AliasedUse : ~mu0_2
# 213| v0_57(void) = ExitFunction :
# 226| char StringLiteralAliasing()
# 226| Block 0

View File

@@ -0,0 +1 @@
semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSASanity.ql

View File

@@ -108,7 +108,9 @@
| captures.cpp:22:3:24:4 | declaration |
| captures.cpp:22:8:22:15 | definition of myLambda |
| captures.cpp:22:8:22:15 | myLambda |
| captures.cpp:22:18:24:3 | [...](...){...} |
| captures.cpp:22:18:24:3 | initializer for myLambda |
| captures.cpp:22:18:24:3 | {...} |
| captures.cpp:22:19:22:19 | (constructor) |
| captures.cpp:22:19:22:19 | (constructor) |
| captures.cpp:22:19:22:19 | (constructor) |
@@ -123,8 +125,6 @@
| captures.cpp:22:19:22:19 | operator= |
| captures.cpp:22:19:22:19 | return ... |
| captures.cpp:22:19:22:19 | { ... } |
| captures.cpp:22:19:24:3 | [...](...){...} |
| captures.cpp:22:19:24:3 | {...} |
| captures.cpp:22:23:22:23 | definition of x |
| captures.cpp:22:23:22:23 | x |
| captures.cpp:22:23:22:23 | x |
@@ -164,7 +164,9 @@
| end_pos.cpp:9:5:11:6 | declaration |
| end_pos.cpp:9:10:9:11 | definition of fp |
| end_pos.cpp:9:10:9:11 | fp |
| end_pos.cpp:9:14:11:5 | [...](...){...} |
| end_pos.cpp:9:14:11:5 | initializer for fp |
| end_pos.cpp:9:14:11:5 | {...} |
| end_pos.cpp:9:15:9:15 | (constructor) |
| end_pos.cpp:9:15:9:15 | (constructor) |
| end_pos.cpp:9:15:9:15 | (constructor) |
@@ -177,8 +179,6 @@
| end_pos.cpp:9:15:9:15 | operator= |
| end_pos.cpp:9:15:9:15 | return ... |
| end_pos.cpp:9:15:9:15 | { ... } |
| end_pos.cpp:9:15:11:5 | [...](...){...} |
| end_pos.cpp:9:15:11:5 | {...} |
| end_pos.cpp:9:17:9:17 | definition of ii |
| end_pos.cpp:9:17:9:17 | ii |
| end_pos.cpp:9:17:9:18 | (reference to) |

View File

@@ -17,7 +17,6 @@ missingOperand
| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() |
| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) |
| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() |

View File

@@ -21,7 +21,6 @@ missingOperand
| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() |
| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) |
| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() |

View File

@@ -17,7 +17,6 @@ missingOperand
| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() |
| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) |
| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() |

View File

@@ -55,3 +55,9 @@ void f(void) {
}
}
// This pattern is used to emulate C++20 concepts in a way that's very light on
// template syntax.
template<typename T1, typename T2>
auto sfinaeTrick(T1 x1, T2 x2) -> decltype(x1 == x2, bool()) { // GOOD
return x1 == x2;
}

View File

@@ -25,8 +25,6 @@
| test.c:25:5:25:16 | ... ? ... : ... | This expression has no effect. | test.c:25:5:25:16 | ... ? ... : ... | |
| test.c:26:15:26:16 | 32 | This expression has no effect. | test.c:26:15:26:16 | 32 | |
| test.c:27:9:27:10 | 33 | This expression has no effect. | test.c:27:9:27:10 | 33 | |
| test.cpp:24:3:24:3 | call to operator++ | This expression has no effect (because $@ has no external side effects). | test.cpp:9:14:9:23 | operator++ | operator++ |
| test.cpp:25:3:25:3 | call to operator++ | This expression has no effect (because $@ has no external side effects). | test.cpp:9:14:9:23 | operator++ | operator++ |
| test.cpp:62:5:62:5 | call to operator= | This expression has no effect (because $@ has no external side effects). | test.cpp:47:14:47:22 | operator= | operator= |
| test.cpp:65:5:65:5 | call to operator= | This expression has no effect (because $@ has no external side effects). | test.cpp:55:7:55:7 | operator= | operator= |
| volatile.c:9:5:9:5 | c | This expression has no effect. | volatile.c:9:5:9:5 | c | |

View File

@@ -21,8 +21,8 @@ public:
MyIterator arg1, arg2;
_It arg3;
++arg1; // pure, does nothing
++arg2; // pure, does nothing
++arg1; // pure, does nothing [NOT DETECTED]
++arg2; // pure, does nothing [NOT DETECTED]
++arg3; // not pure in all cases (when _It is int this has a side-effect)
return arg2;

View File

@@ -9,6 +9,7 @@
| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_sslv3 has not been set |
| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1 has not been set |
| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1_1 has not been set |
| test3.cpp:7:32:7:62 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test3.cpp:7:32:7:62 | call to context | boost::asio::ssl::context::context | test3.cpp:7:32:7:61 | tls | tls | test3.cpp:7:32:7:62 | call to context | no_tlsv1_1 has not been set |
| test.cpp:25:32:25:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:25:32:25:65 | call to context | boost::asio::ssl::context::context | test.cpp:25:32:25:64 | sslv23 | sslv23 | test.cpp:25:32:25:65 | call to context | no_sslv3 has not been set |
| test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_sslv3 has not been set |
| test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set |

View File

@@ -65,13 +65,13 @@ void TestHardcodedProtocols()
////////////////////// Hardcoded algorithms
boost::asio::ssl::context cxt_tlsv12(boost::asio::ssl::context::tlsv12); // BUG
boost::asio::ssl::context cxt_tlsv12c(boost::asio::ssl::context::tlsv12_client); // BUG
boost::asio::ssl::context cxt_tlsv12s(boost::asio::ssl::context::tlsv12_server); // BUG
boost::asio::ssl::context cxt_tlsv12(boost::asio::ssl::context::tlsv12);
boost::asio::ssl::context cxt_tlsv12c(boost::asio::ssl::context::tlsv12_client);
boost::asio::ssl::context cxt_tlsv12s(boost::asio::ssl::context::tlsv12_server);
boost::asio::ssl::context cxt_tlsv13(boost::asio::ssl::context::tlsv13); // BUG
boost::asio::ssl::context cxt_tlsv13c(boost::asio::ssl::context::tlsv13_client); // BUG
boost::asio::ssl::context cxt_tlsv13s(boost::asio::ssl::context::tlsv13_server); // BUG
boost::asio::ssl::context cxt_tlsv13(boost::asio::ssl::context::tlsv13);
boost::asio::ssl::context cxt_tlsv13c(boost::asio::ssl::context::tlsv13_client);
boost::asio::ssl::context cxt_tlsv13s(boost::asio::ssl::context::tlsv13_server);
}
void InterProceduralTest(boost::asio::ssl::context::method m)
@@ -100,11 +100,11 @@ void TestHardcodedProtocols_inter()
////////////////////// Hardcoded algorithms
InterProceduralTest(boost::asio::ssl::context::tlsv12); // BUG
InterProceduralTest(boost::asio::ssl::context::tlsv12_client); // BUG
InterProceduralTest(boost::asio::ssl::context::tlsv12_server); // BUG
InterProceduralTest(boost::asio::ssl::context::tlsv12);
InterProceduralTest(boost::asio::ssl::context::tlsv12_client);
InterProceduralTest(boost::asio::ssl::context::tlsv12_server);
InterProceduralTest(boost::asio::ssl::context::tlsv13); // BUG
InterProceduralTest(boost::asio::ssl::context::tlsv13_client); // BUG
InterProceduralTest(boost::asio::ssl::context::tlsv13_server); // BUG
InterProceduralTest(boost::asio::ssl::context::tlsv13);
InterProceduralTest(boost::asio::ssl::context::tlsv13_client);
InterProceduralTest(boost::asio::ssl::context::tlsv13_server);
}

View File

@@ -0,0 +1,19 @@
#include "asio/boost_simulation.hpp"
// examples from the qhelp...
void useTLS_bad()
{
boost::asio::ssl::context ctx(boost::asio::ssl::context::tls);
ctx.set_options(boost::asio::ssl::context::no_tlsv1); // BAD: missing no_tlsv1_1
// ...
}
void useTLS_good()
{
boost::asio::ssl::context ctx(boost::asio::ssl::context::tls);
ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); // GOOD
// ...
}

View File

@@ -1,4 +1,6 @@
| test.c:15:20:15:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.c:29:20:29:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.c:44:20:44:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.cpp:18:35:18:40 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.c:16:20:16:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.c:32:20:32:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.c:49:20:49:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.cpp:24:35:24:40 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.cpp:63:28:63:33 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.cpp:71:28:71:33 | call to malloc | This allocation does not include space to null-terminate the string. |

View File

@@ -7,18 +7,21 @@
typedef unsigned long size_t;
void *malloc(size_t size);
void free(void *ptr);
char *strcpy(char *s1, const char *s2);
//// Test code /////
void bad0(char *str) {
// BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(strlen(str));
strcpy(buffer, str);
free(buffer);
}
void good0(char *str) {
// GOOD -- Allocating extra byte for terminator
char *buffer = malloc(strlen(str)+1);
strcpy(buffer, str);
free(buffer);
}
@@ -27,6 +30,7 @@ void bad1(char *str) {
int len = strlen(str);
// BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(len);
strcpy(buffer, str);
free(buffer);
}
@@ -34,6 +38,7 @@ void good1(char *str) {
int len = strlen(str);
// GOOD -- Allocating extra byte for terminator
char *buffer = malloc(len+1);
strcpy(buffer, str);
free(buffer);
}
@@ -42,6 +47,7 @@ void bad2(char *str) {
int len = strlen(str);
// BAD -- Not allocating space for '\0' terminator
char *buffer = malloc(len);
strcpy(buffer, str);
free(buffer);
}
@@ -49,18 +55,21 @@ void good2(char *str) {
int len = strlen(str)+1;
// GOOD -- Allocating extra byte for terminator
char *buffer = malloc(len);
strcpy(buffer, str);
free(buffer);
}
void bad3(char *str) {
// BAD -- Not allocating space for '\0' terminator [NOT DETECTED]
char *buffer = malloc(strlen(str) * sizeof(char));
strcpy(buffer, str);
free(buffer);
}
void good3(char *str) {
// GOOD -- Allocating extra byte for terminator
char *buffer = malloc((strlen(str) + 1) * sizeof(char));
strcpy(buffer, str);
free(buffer);
}

View File

@@ -10,23 +10,100 @@ typedef unsigned long size_t;
void *malloc(size_t size);
void free(void *ptr);
size_t wcslen(const wchar_t *s);
wchar_t* wcscpy(wchar_t* s1, const wchar_t* s2);
int sprintf(char *s, const char *format, ...);
int wprintf(const wchar_t *format, ...);
char *strcat(char *s1, const char *s2);
size_t strlen(const char *s);
int strcmp(const char *s1, const char *s2);
//// Test code /////
void bad1(wchar_t *wstr) {
// BAD -- Not allocating space for '\0' terminator
wchar_t *wbuffer = (wchar_t *)malloc(wcslen(wstr));
wcscpy(wbuffer, wstr);
free(wbuffer);
}
void bad2(wchar_t *wstr) {
// BAD -- Not allocating space for '\0' terminator [NOT DETECTED]
wchar_t *wbuffer = (wchar_t *)malloc(wcslen(wstr) * sizeof(wchar_t));
wcscpy(wbuffer, wstr);
free(wbuffer);
}
void good1(wchar_t *wstr) {
// GOOD -- Allocating extra character for terminator
wchar_t *wbuffer = (wchar_t *)malloc((wcslen(wstr) + 1) * sizeof(wchar_t));
wcscpy(wbuffer, wstr);
free(wbuffer);
}
void bad3(char *str) {
// BAD -- zero-termination proved by sprintf (as destination) [NOT DETECTED]
char *buffer = (char *)malloc(strlen(str));
sprintf(buffer, "%s", str);
free(buffer);
}
void decode(char *dest, char *src);
void wdecode(wchar_t *dest, wchar_t *src);
void bad4(char *str) {
// BAD -- zero-termination proved by wprintf (as parameter) [NOT DETECTED]
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);
wprintf(L"%s", buffer);
free(buffer);
}
void bad5(char *str) {
// BAD -- zero-termination proved by strcat (as destination)
char *buffer = (char *)malloc(strlen(str));
buffer[0] = 0;
strcat(buffer, str);
free(buffer);
}
void bad6(char *str, char *dest) {
// BAD -- zero-termination proved by strcat (as source)
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);
strcat(dest, buffer);
free(buffer);
}
void bad7(char *str, char *str2) {
// BAD -- zero-termination proved by strcmp [NOT DETECTED]
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);
if (strcmp(buffer, str2) == 0) {
// ...
}
free(buffer);
}
void bad8(wchar_t *str) {
// BAD -- zero-termination proved by wcslen [NOT DETECTED]
wchar_t *wbuffer = (wchar_t *)malloc(wcslen(str));
wdecode(wbuffer, str);
if (wcslen(wbuffer) == 0) {
// ...
}
free(wbuffer);
}
void good2(char *str, char *dest) {
// GOOD -- zero-termination not proven
char *buffer = (char *)malloc(strlen(str));
decode(buffer, str);
free(buffer);
}
void bad9(wchar_t *wstr) {
// BAD -- using new [NOT DETECTED]
wchar_t *wbuffer = new wchar_t[wcslen(wstr)];
wcscpy(wbuffer, wstr);
delete wbuffer;
}

View File

@@ -0,0 +1,50 @@
///// Library functions //////
typedef unsigned long size_t;
void *malloc(size_t size);
void free(void *ptr);
size_t strlen(const char *s);
namespace std
{
template<class charT> struct char_traits;
template <class T> class allocator {
public:
allocator() throw();
typedef size_t size_type;
};
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_string {
public:
typedef typename Allocator::size_type size_type;
explicit basic_string(const Allocator& a = Allocator());
basic_string(const charT* s, const Allocator& a = Allocator());
basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
const charT* c_str() const;
};
typedef basic_string<char> string;
}
//// Test code /////
void bad1(char *str) {
// BAD -- Not allocating space for '\0' terminator [NOT DETECTED]
char *buffer = (char *)malloc(strlen(str));
std::string str2(buffer);
free(buffer);
}
void good1(char *str) {
// GOOD --- copy does not overrun due to size limit
char *buffer = (char *)malloc(strlen(str));
std::string str2(buffer, strlen(str));
free(buffer);
}