Merge pull request #1 from github/main

update fork
This commit is contained in:
ihsinme
2021-01-28 13:26:11 +03:00
committed by GitHub
518 changed files with 78502 additions and 12073 deletions

3
.gitignore vendored
View File

@@ -17,6 +17,9 @@
# Byte-compiled python files
*.pyc
# python virtual environment folder
.venv/
# It's useful (though not required) to be able to unpack codeql in the ql checkout itself
/codeql/

View File

@@ -27,6 +27,10 @@ class Configuration extends TaintTrackingConfiguration {
override predicate isSink(Element tainted) {
exists(SQLLikeFunction runSql | runSql.outermostWrapperFunctionCall(tainted, _))
}
override predicate isBarrier(Expr e) {
super.isBarrier(e) or e.getUnspecifiedType() instanceof IntegralType
}
}
from

View File

@@ -0,0 +1,35 @@
// BAD: the memset call will probably be removed.
void getPassword(void) {
char pwd[64];
if (GetPassword(pwd, sizeof(pwd))) {
/* Checking of password, secure operations, etc. */
}
memset(pwd, 0, sizeof(pwd));
}
// GOOD: in this case the memset will not be removed.
void getPassword(void) {
char pwd[64];
if (retrievePassword(pwd, sizeof(pwd))) {
/* Checking of password, secure operations, etc. */
}
memset_s(pwd, 0, sizeof(pwd));
}
// GOOD: in this case the memset will not be removed.
void getPassword(void) {
char pwd[64];
if (retrievePassword(pwd, sizeof(pwd))) {
/* Checking of password, secure operations, etc. */
}
SecureZeroMemory(pwd, sizeof(pwd));
}
// GOOD: in this case the memset will not be removed.
void getPassword(void) {
char pwd[64];
if (retrievePassword(pwd, sizeof(pwd))) {
/* Checking of password, secure operations, etc. */
}
#pragma optimize("", off)
memset(pwd, 0, sizeof(pwd));
#pragma optimize("", on)
}

View File

@@ -0,0 +1,31 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Compiler optimization will exclude the cleaning of private information.
Using the <code>memset</code> function to clear private data in a variable that has no subsequent use is potentially dangerous, since the compiler can remove the call.
For some compilers, optimization is also possible when using calls to free memory after the <code>memset</code> function.</p>
<p>It is possible to miss detection of vulnerabilities if used to clear fields of structures or parts of a buffer.</p>
</overview>
<recommendation>
<p>We recommend to use the <code>RtlSecureZeroMemory</code> or <code>memset_s</code> functions, or compilation flags that exclude optimization of <code>memset</code> calls (e.g. -fno-builtin-memset).</p>
</recommendation>
<example>
<p>The following example demonstrates an erroneous and corrected use of the <code>memset</code> function.</p>
<sample src="CompilerRemovalOfCodeToClearBuffers.c" />
</example>
<references>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations">MSC06-C. Beware of compiler optimizations</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,127 @@
/**
* @name Compiler Removal Of Code To Clear Buffers
* @description Using <code>memset</code> the function to clear private data in a variable that has no subsequent use
* is potentially dangerous because the compiler can remove the call.
* @kind problem
* @id cpp/compiler-removal-of-code-to-clear-buffers
* @problem.severity warning
* @precision medium
* @tags security
* external/cwe/cwe-14
*/
import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.dataflow.StackAddress
/**
* A call to `memset` of the form `memset(ptr, value, num)`, for some local variable `ptr`.
*/
class CompilerRemovaMemset extends FunctionCall {
CompilerRemovaMemset() {
this.getTarget().hasGlobalOrStdName("memset") and
exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp |
DataFlow::localFlow(source, sink) and
this.getArgument(0) = isv.getAnAccess() and
(
source.asExpr() = exp
or
// handle the case where exp is defined by an address being passed into some function.
source.asDefiningArgument() = exp
) and
exp.getLocation().getEndLine() < this.getArgument(0).getLocation().getStartLine() and
sink.asExpr() = this.getArgument(0)
)
}
predicate isExistsAllocForThisVariable() {
exists(AllocationExpr alloc, Variable v |
alloc = v.getAnAssignedValue() and
this.getArgument(0) = v.getAnAccess() and
alloc.getASuccessor+() = this
)
or
not stackPointerFlowsToUse(this.getArgument(0), _, _, _)
}
predicate isExistsFreeForThisVariable() {
exists(DeallocationExpr free, Variable v |
this.getArgument(0) = v.getAnAccess() and
free.getFreedExpr() = v.getAnAccess() and
this.getASuccessor+() = free
)
}
predicate isExistsCallWithThisVariableExcludingDeallocationCalls() {
exists(FunctionCall fc, Variable v |
not fc instanceof DeallocationExpr and
this.getArgument(0) = v.getAnAccess() and
fc.getAnArgument() = v.getAnAccess() and
this.getASuccessor+() = fc
)
}
predicate isVariableUseAfterMemsetExcludingCalls() {
exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp |
DataFlow::localFlow(source, sink) and
this.getArgument(0) = isv.getAnAccess() and
source.asExpr() = isv.getAnAccess() and
exp.getLocation().getStartLine() > this.getArgument(2).getLocation().getEndLine() and
not exp.getParent() instanceof FunctionCall and
sink.asExpr() = exp
)
}
predicate isVariableUseBoundWithArgumentFunction() {
exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Parameter p, Expr exp |
DataFlow::localFlow(source, sink) and
this.getArgument(0) = isv.getAnAccess() and
this.getEnclosingFunction().getAParameter() = p and
exp.getAChild*() = p.getAnAccess() and
source.asExpr() = exp and
sink.asExpr() = isv.getAnAccess()
)
}
predicate isVariableUseBoundWithGlobalVariable() {
exists(
DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, GlobalVariable gv, Expr exp
|
DataFlow::localFlow(source, sink) and
this.getArgument(0) = isv.getAnAccess() and
exp.getAChild*() = gv.getAnAccess() and
source.asExpr() = exp and
sink.asExpr() = isv.getAnAccess()
)
}
predicate isExistsCompilationFlagsBlockingRemoval() {
exists(Compilation c |
c.getAFileCompiled() = this.getFile() and
c.getAnArgument() = "-fno-builtin-memset"
)
}
predicate isUseVCCompilation() {
exists(Compilation c |
c.getAFileCompiled() = this.getFile() and
(
c.getArgument(2).matches("%gcc%") or
c.getArgument(2).matches("%g++%") or
c.getArgument(2).matches("%clang%") or
c.getArgument(2) = "--force-recompute"
)
)
}
}
from CompilerRemovaMemset fc
where
not (fc.isExistsAllocForThisVariable() and not fc.isExistsFreeForThisVariable()) and
not (fc.isExistsFreeForThisVariable() and not fc.isUseVCCompilation()) and
not fc.isVariableUseAfterMemsetExcludingCalls() and
not fc.isExistsCallWithThisVariableExcludingDeallocationCalls() and
not fc.isVariableUseBoundWithArgumentFunction() and
not fc.isVariableUseBoundWithGlobalVariable() and
not fc.isExistsCompilationFlagsBlockingRemoval()
select fc.getArgument(0), "This variable will not be cleared."

View File

@@ -16,6 +16,6 @@ import DataFlow::PathGraph
from WriteConfig b, DataFlow::PathNode source, DataFlow::PathNode sink
where b.hasFlowPath(source, sink)
select sink.getNode(),
"This write into the external location '" + sink + "' may contain unencrypted data from $@",
source, "this source."
select sink.getNode(), source, sink,
"This write into the external location '" + sink.getNode() +
"' may contain unencrypted data from $@", source, "this source."

View File

@@ -12,6 +12,20 @@
*/
import cpp
import semmle.code.cpp.controlflow.Guards
/**
* A function call that potentially does not return (such as `exit`).
*/
class CallMayNotReturn extends FunctionCall {
CallMayNotReturn() {
// call that is known to not return
not exists(this.(ControlFlowNode).getASuccessor())
or
// call to another function that may not return
exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction())
}
}
/**
* A call to `realloc` of the form `v = realloc(v, size)`, for some variable `v`.
@@ -30,40 +44,19 @@ class ReallocCallLeak extends FunctionCall {
)
}
predicate isExistsIfWithExitCall() {
exists(IfStmt ifc |
this.getArgument(0) = v.getAnAccess() and
ifc.getCondition().getAChild*() = v.getAnAccess() and
ifc.getEnclosingFunction() = this.getEnclosingFunction() and
ifc.getLocation().getStartLine() >= this.getArgument(0).getLocation().getStartLine() and
exists(FunctionCall fc |
fc.getTarget().hasName("exit") and
fc.getEnclosingFunction() = this.getEnclosingFunction() and
(ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc)
)
or
exists(FunctionCall fc, FunctionCall ftmp1, FunctionCall ftmp2 |
ftmp1.getTarget().hasName("exit") and
ftmp2.(ControlFlowNode).getASuccessor*() = ftmp1 and
fc = ftmp2.getEnclosingFunction().getACallToThisFunction() and
fc.getEnclosingFunction() = this.getEnclosingFunction() and
(ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc)
)
)
}
predicate isExistsAssertWithArgumentCall() {
exists(FunctionCall fc |
fc.getTarget().hasName("__assert_fail") and
this.getEnclosingFunction() = fc.getEnclosingFunction() and
fc.getLocation().getStartLine() > this.getArgument(0).getLocation().getEndLine() and
fc.getArgument(0).toString().matches("%" + this.getArgument(0).toString() + "%")
/**
* Holds if failure of this allocation may be handled by termination, for
* example a call to `exit()`.
*/
predicate mayHandleByTermination() {
exists(GuardCondition guard, CallMayNotReturn exit |
this.(ControlFlowNode).getASuccessor*() = guard and
guard.getAChild*() = v.getAnAccess() and
guard.controls(exit.getBasicBlock(), _)
)
}
}
from ReallocCallLeak rcl
where
not rcl.isExistsIfWithExitCall() and
not rcl.isExistsAssertWithArgumentCall()
where not rcl.mayHandleByTermination()
select rcl, "possible loss of original pointer on unsuccessful call realloc"

View File

@@ -0,0 +1,4 @@
strncat(dest, source, sizeof(dest) - strlen(dest)); // BAD: writes a zero byte past the `dest` buffer.
strncat(dest, source, sizeof(dest) - strlen(dest) -1); // GOOD: Reserves space for the zero byte.

View File

@@ -0,0 +1,32 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The standard library function <code>strncat(dest, source, count)</code> appends the <code>source</code> string to the <code>dest</code> string. <code>count</code> specifies the maximum number of characters to append and must be less than the remaining space in the target buffer. Calls of the form <code> strncat (dest, source, sizeof (dest) - strlen (dest)) </code> set the third argument to one more than possible. So when the <code>dest</code> is full, the expression <code> sizeof (dest) - strlen (dest) </code> will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the <code>dest</code> buffer.</p>
</overview>
<recommendation>
<p>We recommend subtracting one from the third argument. For example, replace <code>strncat(dest, source, sizeof(dest)-strlen(dest))</code> with <code>strncat(dest, source, sizeof(dest)-strlen(dest)-1)</code>.</p>
</recommendation>
<example>
<p>The following example demonstrates an erroneous and corrected use of the <code>strncat</code> function.</p>
<sample src="AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c" />
</example>
<references>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator">STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator</a>.
</li>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C.+Do+not+form+or+use+out-of-bounds+pointers+or+array+subscripts">ARR30-C. Do not form or use out-of-bounds pointers or array subscripts</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,64 @@
/**
* @name Access Of Memory Location After The End Of A Buffer Using Strncat
* @description Calls of the form `strncat(dest, source, sizeof (dest) - strlen (dest))` set the third argument to one more than possible. So when `dest` is full, the expression `sizeof(dest) - strlen (dest)` will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the `dest` buffer.
* @kind problem
* @id cpp/access-memory-location-after-end-buffer
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-788
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* A call to `strncat` of the form `strncat(buff, str, someExpr - strlen(buf))`, for some expression `someExpr` equal to `sizeof(buff)`.
*/
class WrongCallStrncat extends FunctionCall {
Expr leftsomeExpr;
WrongCallStrncat() {
this.getTarget().hasGlobalOrStdName("strncat") and
// the expression of the first argument in `strncat` and `strnlen` is identical
globalValueNumber(this.getArgument(0)) =
globalValueNumber(this.getArgument(2).(SubExpr).getRightOperand().(StrlenCall).getStringExpr()) and
// using a string constant often speaks of manually calculating the length of the required buffer.
(
not this.getArgument(1) instanceof StringLiteral and
not this.getArgument(1) instanceof CharLiteral
) and
// for use in predicates
leftsomeExpr = this.getArgument(2).(SubExpr).getLeftOperand()
}
/**
* Holds if the left side of the expression `someExpr` equal to `sizeof(buf)`.
*/
predicate isExpressionEqualSizeof() {
// the left side of the expression `someExpr` is `sizeof(buf)`.
globalValueNumber(this.getArgument(0)) =
globalValueNumber(leftsomeExpr.(SizeofExprOperator).getExprOperand())
or
// value of the left side of the expression `someExpr` equal `sizeof(buf)` value, and `buf` is array.
leftsomeExpr.getValue().toInt() = this.getArgument(0).getType().getSize()
}
/**
* Holds if the left side of the expression `someExpr` equal to variable containing the length of the memory allocated for the buffer.
*/
predicate isVariableEqualValueSizegBuffer() {
// the left side of expression `someExpr` is the variable that was used in the function of allocating memory for the buffer`.
exists(AllocationExpr alc |
leftsomeExpr.(VariableAccess).getTarget() =
alc.(FunctionCall).getArgument(0).(VariableAccess).getTarget()
)
}
}
from WrongCallStrncat sc
where
sc.isExpressionEqualSizeof() or
sc.isVariableEqualValueSizegBuffer()
select sc, "if the used buffer is full, writing out of the buffer is possible"

View File

@@ -50,5 +50,5 @@ class CStyleComment extends Comment {
* ```
*/
class CppStyleComment extends Comment {
CppStyleComment() { this.getContents().prefix(2) = "//" }
CppStyleComment() { this.getContents().matches("//%") }
}

View File

@@ -334,6 +334,18 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
)
}
/**
* Gets the class of which this function, called `memberName`, is a member.
*
* Prefer to use `getDeclaringType()` or `getName()` directly if you do not
* need to reason about both.
*/
pragma[nomagic]
Class getClassAndName(string memberName) {
this.hasName(memberName) and
this.getDeclaringType() = result
}
/**
* Implements `ControlFlowNode.getControlFlowScope`. The `Function` is
* used to represent the exit node of the control flow graph, so it is

View File

@@ -274,7 +274,7 @@ class Type extends Locatable, @type {
/**
* Gets this type with any typedefs resolved. For example, given
* `typedef C T`, this would resolve `const T&amp;` to `const C&amp;`.
* `typedef C T`, this would resolve `const T&` to `const C&`.
* Note that this will only work if the resolved type actually appears
* on its own elsewhere in the program.
*/
@@ -1544,9 +1544,9 @@ class FunctionPointerIshType extends DerivedType {
/**
* A C++ pointer to data member. See 15.5.
* ```
* class C { int m; };
* class C { public: int m; };
* int C::* p = &C::m; // pointer to data member m of class C
* class C *;
* class C c;
* int val = c.*p; // access data member
* ```
*/

View File

@@ -87,7 +87,7 @@ abstract class MutexType extends Type {
private Function mustlockCandidate() {
exists(string name | name = result.getName() |
name = "lock" or
name.suffix(name.length() - 10) = "mutex_lock"
name.matches("%mutex\\_lock")
)
}
@@ -97,7 +97,7 @@ private Function mustlockCandidate() {
private Function trylockCandidate() {
exists(string name | name = result.getName() |
name = "try_lock" or
name.suffix(name.length() - 13) = "mutex_trylock"
name.matches("%mutex\\_trylock")
)
}
@@ -107,7 +107,7 @@ private Function trylockCandidate() {
private Function unlockCandidate() {
exists(string name | name = result.getName() |
name = "unlock" or
name.suffix(name.length() - 12) = "mutex_unlock"
name.matches("%mutex\\_unlock")
)
}

View File

@@ -545,6 +545,9 @@ module TaintedWithPath {
/** Override this to specify which elements are sinks in this configuration. */
abstract predicate isSink(Element e);
/** Override this to specify which expressions are barriers in this configuration. */
predicate isBarrier(Expr e) { nodeIsBarrier(getNodeForExpr(e)) }
/**
* Override this predicate to `any()` to allow taint to flow through global
* variables.
@@ -578,7 +581,9 @@ module TaintedWithPath {
)
}
override predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) }
override predicate isBarrier(DataFlow::Node node) {
exists(TaintTrackingConfiguration cfg, Expr e | cfg.isBarrier(e) and node = getNodeForExpr(e))
}
override predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) }
}

View File

@@ -2,6 +2,7 @@ private import cpp
private import DataFlowUtil
private import semmle.code.cpp.ir.IR
private import DataFlowDispatch
private import semmle.code.cpp.models.interfaces.DataFlow
/**
* A data flow node that occurs as the argument of a call and is passed as-is
@@ -209,6 +210,13 @@ private class FieldContent extends Content, TFieldContent {
predicate hasOffset(Class cl, int start, int end) { cl = c and start = startBit and end = endBit }
Field getAField() { result = getAField(c, startBit, endBit) }
pragma[noinline]
Field getADirectField() {
c = result.getDeclaringType() and
this.getAField() = result and
this.hasOffset(c, _, _)
}
}
private class CollectionContent extends Content, TCollectionContent {
@@ -221,69 +229,101 @@ private class ArrayContent extends Content, TArrayContent {
override string toString() { result = "array content" }
}
private predicate fieldStoreStepNoChi(Node node1, FieldContent f, PostUpdateNode node2) {
exists(StoreInstruction store, Class c |
store = node2.asInstruction() and
/**
* A store step from the value of a `StoreInstruction` to the "innermost" field of the destination.
* This predicate only holds when there is no `ChiInsturction` that merges the result of the
* `StoreInstruction` into a larger memory.
*/
private predicate instrToFieldNodeStoreStepNoChi(
Node node1, FieldContent f, PartialDefinitionNode node2
) {
exists(StoreInstruction store, PartialFieldDefinition pd |
pd = node2.getPartialDefinition() and
not exists(ChiInstruction chi | chi.getPartial() = store) and
pd.getPreUpdateNode() = GetFieldNode::fromInstruction(store.getDestinationAddress()) and
store.getSourceValueOperand() = node1.asOperand() and
getWrittenField(store, f.(FieldContent).getAField(), c) and
f.hasOffset(c, _, _)
f.getADirectField() = pd.getPreUpdateNode().getField()
)
}
private FieldAddressInstruction getFieldInstruction(Instruction instr) {
result = instr or
result = instr.(CopyValueInstruction).getUnary()
}
pragma[noinline]
private predicate getWrittenField(Instruction instr, Field f, Class c) {
exists(FieldAddressInstruction fa |
fa =
getFieldInstruction([
instr.(StoreInstruction).getDestinationAddress(),
instr.(WriteSideEffectInstruction).getDestinationAddress()
]) and
f = fa.getField() and
c = f.getDeclaringType()
)
}
private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode node2) {
exists(ChiPartialOperand operand, ChiInstruction chi |
chi.getPartialOperand() = operand and
/**
* A store step from a `StoreInstruction` to the "innermost" field
* of the destination. This predicate only holds when there exists a `ChiInstruction` that merges the
* result of the `StoreInstruction` into a larger memory.
*/
private predicate instrToFieldNodeStoreStepChi(
Node node1, FieldContent f, PartialDefinitionNode node2
) {
exists(
ChiPartialOperand operand, StoreInstruction store, ChiInstruction chi, PartialFieldDefinition pd
|
pd = node2.getPartialDefinition() and
not chi.isResultConflated() and
node1.asOperand() = operand and
node2.asInstruction() = chi and
exists(Class c |
c = chi.getResultType() and
exists(int startBit, int endBit |
chi.getUpdatedInterval(startBit, endBit) and
f.hasOffset(c, startBit, endBit)
)
or
getWrittenField(operand.getDef(), f.getAField(), c) and
f.hasOffset(c, _, _)
chi.getPartialOperand() = operand and
store = operand.getDef() and
pd.getPreUpdateNode() = GetFieldNode::fromInstruction(store.getDestinationAddress()) and
f.getADirectField() = pd.getPreUpdateNode().getField()
)
}
private predicate callableWithoutDefinitionStoreStep(
Node node1, FieldContent f, PartialDefinitionNode node2
) {
exists(
WriteSideEffectInstruction write, ChiInstruction chi, PartialFieldDefinition pd,
Function callable, CallInstruction call
|
chi.getPartial() = write and
not chi.isResultConflated() and
pd = node2.getPartialDefinition() and
pd.getPreUpdateNode() = GetFieldNode::fromInstruction(write.getDestinationAddress()) and
f.getADirectField() = pd.getPreUpdateNode().getField() and
call = write.getPrimaryInstruction() and
callable = call.getStaticCallTarget() and
not callable.hasDefinition()
|
exists(OutParameterDeref out | out.getIndex() = write.getIndex() |
callable.(DataFlowFunction).hasDataFlow(_, out) and
node1.asInstruction() = write
)
or
// Ideally we shouldn't need to do a store step from a read side effect, but if we don't have a
// model for the callee there might not be flow to the write side effect (since the callee has no
// definition). This case ensures that we propagate dataflow when a field is passed into a
// function that has a write side effect, even though the write side effect doesn't have incoming
// flow.
not callable instanceof DataFlowFunction and
exists(ReadSideEffectInstruction read | call = read.getPrimaryInstruction() |
node1.asInstruction() = read.getSideEffectOperand().getAnyDef()
)
)
}
private predicate arrayStoreStepChi(Node node1, ArrayContent a, PostUpdateNode node2) {
/**
* A store step from a `StoreInstruction` to the `ChiInstruction` generated from assigning
* to a pointer or array indirection
*/
private predicate arrayStoreStepChi(Node node1, ArrayContent a, PartialDefinitionNode node2) {
a = TArrayContent() and
exists(ChiPartialOperand operand, ChiInstruction chi, StoreInstruction store |
exists(
ChiPartialOperand operand, ChiInstruction chi, StoreInstruction store, PartialDefinition pd
|
pd = node2.getPartialDefinition() and
chi.getPartialOperand() = operand and
store = operand.getDef() and
node1.asOperand() = operand and
// This `ChiInstruction` will always have a non-conflated result because both `ArrayStoreNode`
// and `PointerStoreNode` require it in their characteristic predicates.
node2.asInstruction() = chi and
(
// `x[i] = taint()`
// This matches the characteristic predicate in `ArrayStoreNode`.
store.getDestinationAddress() instanceof PointerAddInstruction
or
// `*p = taint()`
// This matches the characteristic predicate in `PointerStoreNode`.
store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction
)
pd.getPreUpdateNode().asOperand() = chi.getTotalOperand()
|
// `x[i] = taint()`
// This matches the characteristic predicate in `ArrayStoreNode`.
store.getDestinationAddress() instanceof PointerAddInstruction
or
// `*p = taint()`
// This matches the characteristic predicate in `PointerStoreNode`.
store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction
)
}
@@ -293,82 +333,10 @@ private predicate arrayStoreStepChi(Node node1, ArrayContent a, PostUpdateNode n
* value of `node1`.
*/
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
fieldStoreStepNoChi(node1, f, node2) or
fieldStoreStepChi(node1, f, node2) or
instrToFieldNodeStoreStepNoChi(node1, f, node2) or
instrToFieldNodeStoreStepChi(node1, f, node2) or
arrayStoreStepChi(node1, f, node2) or
fieldStoreStepAfterArraySuppression(node1, f, node2)
}
// This predicate pushes the correct `FieldContent` onto the access path when the
// `suppressArrayRead` predicate has popped off an `ArrayContent`.
private predicate fieldStoreStepAfterArraySuppression(
Node node1, FieldContent f, PostUpdateNode node2
) {
exists(WriteSideEffectInstruction write, ChiInstruction chi, Class c |
not chi.isResultConflated() and
node1.asInstruction() = chi and
node2.asInstruction() = chi and
chi.getPartial() = write and
getWrittenField(write, f.getAField(), c) and
f.hasOffset(c, _, _)
)
}
bindingset[result, i]
private int unbindInt(int i) { i <= result and i >= result }
pragma[noinline]
private predicate getLoadedField(LoadInstruction load, Field f, Class c) {
exists(FieldAddressInstruction fa |
fa = load.getSourceAddress() and
f = fa.getField() and
c = f.getDeclaringType()
)
}
/**
* Holds if data can flow from `node1` to `node2` via a read of `f`.
* Thus, `node1` references an object with a field `f` whose value ends up in
* `node2`.
*/
private predicate fieldReadStep(Node node1, FieldContent f, Node node2) {
exists(LoadOperand operand |
node2.asOperand() = operand and
node1.asInstruction() = operand.getAnyDef() and
exists(Class c |
c = operand.getAnyDef().getResultType() and
exists(int startBit, int endBit |
operand.getUsedInterval(unbindInt(startBit), unbindInt(endBit)) and
f.hasOffset(c, startBit, endBit)
)
or
getLoadedField(operand.getUse(), f.getAField(), c) and
f.hasOffset(c, _, _)
)
)
}
/**
* When a store step happens in a function that looks like an array write such as:
* ```cpp
* void f(int* pa) {
* pa = source();
* }
* ```
* it can be a write to an array, but it can also happen that `f` is called as `f(&a.x)`. If that is
* the case, the `ArrayContent` that was written by the call to `f` should be popped off the access
* path, and a `FieldContent` containing `x` should be pushed instead.
* So this case pops `ArrayContent` off the access path, and the `fieldStoreStepAfterArraySuppression`
* predicate in `storeStep` ensures that we push the right `FieldContent` onto the access path.
*/
predicate suppressArrayRead(Node node1, ArrayContent a, Node node2) {
a = TArrayContent() and
exists(WriteSideEffectInstruction write, ChiInstruction chi |
node1.asInstruction() = write and
node2.asInstruction() = chi and
chi.getPartial() = write and
getWrittenField(write, _, _)
)
callableWithoutDefinitionStoreStep(node1, f, node2)
}
private class ArrayToPointerConvertInstruction extends ConvertInstruction {
@@ -378,34 +346,96 @@ private class ArrayToPointerConvertInstruction extends ConvertInstruction {
}
}
private Instruction skipOneCopyValueInstructionRec(CopyValueInstruction copy) {
copy.getUnary() = result and not result instanceof CopyValueInstruction
or
result = skipOneCopyValueInstructionRec(copy.getUnary())
private class InexactLoadOperand extends LoadOperand {
InexactLoadOperand() { this.isDefinitionInexact() }
}
private Instruction skipCopyValueInstructions(Operand op) {
not result instanceof CopyValueInstruction and result = op.getDef()
/** Get the result type of `i`, if it is a `PointerType`. */
private PointerType getPointerType(Instruction i) {
// We are done if the type is a pointer type that is not a glvalue
i.getResultLanguageType().hasType(result, false)
or
result = skipOneCopyValueInstructionRec(op.getDef())
// Some instructions produce a glvalue. Recurse past those to get the actual `PointerType`.
result = getPointerType(i.(PointerOffsetInstruction).getLeft())
}
pragma[noinline]
private predicate deconstructLoad(
LoadInstruction load, InexactLoadOperand loadOperand, Instruction addressInstr
) {
load.getSourceAddress() = addressInstr and
load.getSourceValueOperand() = loadOperand
}
private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) {
a = TArrayContent() and
// Explicit dereferences such as `*p` or `p[i]` where `p` is a pointer or array.
exists(LoadOperand operand, Instruction address |
operand.isDefinitionInexact() and
node1.asInstruction() = operand.getAnyDef() and
operand = node2.asOperand() and
address = skipCopyValueInstructions(operand.getAddressOperand()) and
(
address instanceof LoadInstruction or
address instanceof ArrayToPointerConvertInstruction or
address instanceof PointerOffsetInstruction
)
exists(InexactLoadOperand loadOperand, LoadInstruction load, Instruction address |
deconstructLoad(load, loadOperand, address) and
node1.asInstruction() = loadOperand.getAnyDef() and
not node1.asInstruction().isResultConflated() and
loadOperand = node2.asOperand() and
// Ensure that the load is actually loading from an array or a pointer.
getPointerType(address).getBaseType() = load.getResultType()
)
}
/** Step from the value loaded by a `LoadInstruction` to the "outermost" loaded field. */
private predicate instrToFieldNodeReadStep(FieldNode node1, FieldContent f, Node node2) {
(
node1.getNextNode() = node2
or
not exists(node1.getNextNode()) and
(
exists(LoadInstruction load |
node2.asInstruction() = load and
node1 = GetFieldNode::fromInstruction(load.getSourceAddress())
)
or
exists(ReadSideEffectInstruction read |
node2.asOperand() = read.getSideEffectOperand() and
node1 = GetFieldNode::fromInstruction(read.getArgumentDef())
)
)
) and
f.getADirectField() = node1.getField()
}
bindingset[result, i]
private int unbindInt(int i) { i <= result and i >= result }
pragma[noinline]
private FieldNode getFieldNodeFromLoadOperand(LoadOperand loadOperand) {
result = GetFieldNode::fromOperand(loadOperand.getAddressOperand())
}
/**
* Sometimes there's no explicit field dereference. In such cases we use the IR alias analysis to
* determine the offset being, and deduce the field from this information.
*/
private predicate aliasedReadStep(Node node1, FieldContent f, Node node2) {
exists(LoadOperand operand, Class c, int startBit, int endBit |
// Ensure that we don't already catch this store step using a `FieldNode`.
not instrToFieldNodeReadStep(getFieldNodeFromLoadOperand(operand), f, _) and
node1.asInstruction() = operand.getAnyDef() and
node2.asOperand() = operand and
not node1.asInstruction().isResultConflated() and
c = operand.getAnyDef().getResultType() and
f.hasOffset(c, startBit, endBit) and
operand.getUsedInterval(unbindInt(startBit), unbindInt(endBit))
)
}
/** Get the result type of an `Instruction` i, if it is a `ReferenceType`. */
private ReferenceType getReferenceType(Instruction i) {
i.getResultLanguageType().hasType(result, false)
}
pragma[noinline]
Type getResultTypeOfSourceValue(CopyValueInstruction copy) {
result = copy.getSourceValue().getResultType()
}
/**
* In cases such as:
* ```cpp
@@ -417,21 +447,25 @@ private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) {
* f(&x);
* use(x);
* ```
* the load on `x` in `use(x)` will exactly overlap with its definition (in this case the definition
* is a `WriteSideEffect`). This predicate pops the `ArrayContent` (pushed by the store in `f`)
* from the access path.
* the store to `*pa` in `f` will push `ArrayContent` onto the access path. The `innerRead` predicate
* pops the `ArrayContent` off the access path when a value-to-pointer or value-to-reference conversion
* happens on the argument that is ends up as the target of such a store.
*/
private predicate exactReadStep(Node node1, ArrayContent a, Node node2) {
private predicate innerReadStep(Node node1, Content a, Node node2) {
a = TArrayContent() and
exists(WriteSideEffectInstruction write, ChiInstruction chi |
not chi.isResultConflated() and
chi.getPartial() = write and
exists(WriteSideEffectInstruction write, CallInstruction call, CopyValueInstruction copyValue |
write.getPrimaryInstruction() = call and
node1.asInstruction() = write and
node2.asInstruction() = chi and
// To distinquish this case from the `arrayReadStep` case we require that the entire variable was
// overwritten by the `WriteSideEffectInstruction` (i.e., there is a load that reads the
// entire variable).
exists(LoadInstruction load | load.getSourceValue() = chi)
(
not exists(ChiInstruction chi | chi.getPartial() = write)
or
exists(ChiInstruction chi | chi.getPartial() = write and not chi.isResultConflated())
) and
node2.asInstruction() = write and
copyValue = call.getArgument(write.getIndex()) and
// Check that `copyValue` is actually doing a T to a T* conversion.
[getPointerType(copyValue).getBaseType(), getReferenceType(copyValue).getBaseType()].stripType() =
getResultTypeOfSourceValue(copyValue).stripType()
)
}
@@ -441,10 +475,10 @@ private predicate exactReadStep(Node node1, ArrayContent a, Node node2) {
* `node2`.
*/
predicate readStep(Node node1, Content f, Node node2) {
fieldReadStep(node1, f, node2) or
aliasedReadStep(node1, f, node2) or
arrayReadStep(node1, f, node2) or
exactReadStep(node1, f, node2) or
suppressArrayRead(node1, f, node2)
instrToFieldNodeReadStep(node1, f, node2) or
innerReadStep(node1, f, node2)
}
/**

View File

@@ -15,7 +15,11 @@ cached
private newtype TIRDataFlowNode =
TInstructionNode(Instruction i) or
TOperandNode(Operand op) or
TVariableNode(Variable var)
TVariableNode(Variable var) or
// `FieldNodes` are used as targets of certain `storeStep`s to implement handling of stores to
// nested structs.
TFieldNode(FieldAddressInstruction field) or
TPartialDefinitionNode(PartialDefinition pd)
/**
* A node in a data flow graph.
@@ -28,7 +32,22 @@ class Node extends TIRDataFlowNode {
/**
* INTERNAL: Do not use.
*/
Declaration getEnclosingCallable() { none() } // overridden in subclasses
final Declaration getEnclosingCallable() {
result = unique(Declaration d | d = this.getEnclosingCallableImpl() | d)
}
final private Declaration getEnclosingCallableImpl() {
result = this.asInstruction().getEnclosingFunction() or
result = this.asOperand().getUse().getEnclosingFunction() or
// When flow crosses from one _enclosing callable_ to another, the
// interprocedural data-flow library discards call contexts and inserts a
// node in the big-step relation used for human-readable path explanations.
// Therefore we want a distinct enclosing callable for each `VariableNode`,
// and that can be the `Variable` itself.
result = this.asVariable() or
result = this.(FieldNode).getFieldInstruction().getEnclosingFunction() or
result = this.(PartialDefinitionNode).getPreUpdateNode().getFunction()
}
/** Gets the function to which this node belongs, if any. */
Function getFunction() { none() } // overridden in subclasses
@@ -133,8 +152,6 @@ class InstructionNode extends Node, TInstructionNode {
/** Gets the instruction corresponding to this node. */
Instruction getInstruction() { result = instr }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Function getFunction() { result = instr.getEnclosingFunction() }
override IRType getType() { result = instr.getResultIRType() }
@@ -159,8 +176,6 @@ class OperandNode extends Node, TOperandNode {
/** Gets the operand corresponding to this node. */
Operand getOperand() { result = op }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Function getFunction() { result = op.getUse().getEnclosingFunction() }
override IRType getType() { result = op.getIRType() }
@@ -170,6 +185,139 @@ class OperandNode extends Node, TOperandNode {
override string toString() { result = this.getOperand().toString() }
}
/**
* INTERNAL: do not use. Encapsulates the details of getting a `FieldNode` from
* an `Instruction` or an `Operand`.
*/
module GetFieldNode {
/** An abstract class that defines conversion-like instructions. */
abstract private class SkippableInstruction extends Instruction {
abstract Instruction getSourceInstruction();
}
/**
* Gets the instruction that is propaged through a non-empty sequence of conversion-like instructions.
*/
private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) {
result = skip.getSourceInstruction() and not result instanceof SkippableInstruction
or
result = skipSkippableInstructionsRec(skip.getSourceInstruction())
}
/**
* Gets the instruction that is propagated through a (possibly empty) sequence of conversion-like
* instructions.
*/
private Instruction skipSkippableInstructions(Instruction instr) {
result = instr and not result instanceof SkippableInstruction
or
result = skipSkippableInstructionsRec(instr)
}
private class SkippableCopyValueInstruction extends SkippableInstruction, CopyValueInstruction {
override Instruction getSourceInstruction() { result = this.getSourceValue() }
}
private class SkippableConvertInstruction extends SkippableInstruction, ConvertInstruction {
override Instruction getSourceInstruction() { result = this.getUnary() }
}
private class SkippableCheckedConvertInstruction extends SkippableInstruction,
CheckedConvertOrNullInstruction {
override Instruction getSourceInstruction() { result = this.getUnary() }
}
private class SkippableInheritanceConversionInstruction extends SkippableInstruction,
InheritanceConversionInstruction {
override Instruction getSourceInstruction() { result = this.getUnary() }
}
/**
* INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if
* `instr` is an instruction that propagates an address of a `FieldAddressInstruction`.
*/
FieldNode fromInstruction(Instruction instr) {
result.getFieldInstruction() = skipSkippableInstructions(instr)
}
/**
* INTERNAL: do not use. Gets the `FieldNode` corresponding to `op`, if the definition
* of `op` is an instruction that propagates an address of a `FieldAddressInstruction`.
*/
FieldNode fromOperand(Operand op) { result = fromInstruction(op.getDef()) }
}
/**
* INTERNAL: do not use. A `FieldNode` represents the state of a field before any partial definitions
* of the field. For instance, in the snippet:
* ```cpp
* struct A { struct B { int c; } b; };
* // ...
* A a;
* f(a.b.c);
* ```
* there are two `FieldNode`s: one corresponding to `c`, and one corresponding to `b`. Similarly,
* in `a.b.c = x` there are two `FieldNode`s: one for `c` and one for `b`.
*/
class FieldNode extends Node, TFieldNode {
FieldAddressInstruction field;
FieldNode() { this = TFieldNode(field) }
/** Gets the `Field` of this `FieldNode`. */
Field getField() { result = getFieldInstruction().getField() }
/** Gets the `FieldAddressInstruction` of this `FieldNode`. */
FieldAddressInstruction getFieldInstruction() { result = field }
/**
* Gets the `FieldNode` corresponding to the parent field of this `FieldNode`, if any.
*
* For example, if `f` is the `FieldNode` for `c` in the expression `a.b.c`, then `f.getObjectNode()`
* gives the `FieldNode` of `b`, and `f.getObjectNode().getObjectNode()` has no result as `a` is
* not a field.
*/
FieldNode getObjectNode() { result = GetFieldNode::fromInstruction(field.getObjectAddress()) }
/**
* Gets the `FieldNode` that has this `FieldNode` as parent, if any.
*
* For example, if `f` is the `FieldNode` corresponding to `b` in `a.b.c`, then `f.getNextNode()`
* gives the `FieldNode` corresponding to `c`, and `f.getNextNode().getNextNode()`.
*/
FieldNode getNextNode() { result.getObjectNode() = this }
/** Gets the class where the field of this node is declared. */
Class getDeclaringType() { result = getField().getDeclaringType() }
override Function getFunction() { result = field.getEnclosingFunction() }
override IRType getType() { result = field.getResultIRType() }
override Location getLocation() { result = field.getLocation() }
override string toString() { result = this.getField().toString() }
}
/**
* INTERNAL: do not use. A partial definition of a `FieldNode`.
*/
class PartialFieldDefinition extends FieldNode, PartialDefinition {
/**
* The pre-update node of a partial definition of a `FieldNode` is the `FieldNode` itself. This ensures
* that the data flow library's reverse read mechanism builds up the correct access path for nested
* fields.
* For instance, in `a.b.c = x` there is a partial definition for `c` (let's call it `post[c]`) and a
* partial definition for `b` (let's call it `post[b]`), and there is a read step from `b` to `c`
* (using `instrToFieldNodeReadStep`), so there is a store step from `post[c]` to `post[b]`.
*/
override FieldNode getPreUpdateNode() { result = this }
override Expr getDefinedExpr() {
result = this.getFieldInstruction().getObjectAddress().getUnconvertedResultExpression()
}
}
/**
* An expression, viewed as a node in a data flow graph.
*/
@@ -307,11 +455,26 @@ deprecated class UninitializedNode extends Node {
* This class exists to match the interface used by Java. There are currently no non-abstract
* classes that extend it. When we implement field flow, we can revisit this.
*/
abstract class PostUpdateNode extends InstructionNode {
abstract class PostUpdateNode extends Node {
/**
* Gets the node before the state update.
*/
abstract Node getPreUpdateNode();
override Function getFunction() { result = getPreUpdateNode().getFunction() }
override IRType getType() { result = getPreUpdateNode().getType() }
override Location getLocation() { result = getPreUpdateNode().getLocation() }
}
/** INTERNAL: do not use. A partial definition of a node. */
abstract class PartialDefinition extends Node {
/** Gets the node before the state update. */
abstract Node getPreUpdateNode();
/** Gets the expression that is partially defined by this node. */
abstract Expr getDefinedExpr();
}
/**
@@ -327,112 +490,40 @@ abstract class PostUpdateNode extends InstructionNode {
* setY(&x); // a partial definition of the object `x`.
* ```
*/
abstract private class PartialDefinitionNode extends PostUpdateNode {
abstract Expr getDefinedExpr();
}
class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
PartialDefinition pd;
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
override ChiInstruction instr;
StoreInstruction store;
PartialDefinitionNode() { this = TPartialDefinitionNode(pd) }
ExplicitFieldStoreQualifierNode() {
not instr.isResultConflated() and
instr.getPartial() = store and
(
instr.getUpdatedInterval(_, _) or
store.getDestinationAddress() instanceof FieldAddressInstruction
)
}
/** Gets the expression that is partially defined by this node, if any. */
Expr getDefinedExpr() { result = pd.getDefinedExpr() }
// By using an operand as the result of this predicate we avoid the dataflow inconsistency errors
// caused by having multiple nodes sharing the same pre update node. This inconsistency error can cause
// a tuple explosion in the big step dataflow relation since it can make many nodes be the entry node
// into a big step.
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
override Node getPreUpdateNode() { result = pd.getPreUpdateNode() }
override Expr getDefinedExpr() {
result =
store
.getDestinationAddress()
.(FieldAddressInstruction)
.getObjectAddress()
.getUnconvertedResultExpression()
}
}
/** Gets the `PartialDefinition` associated with this node. */
PartialDefinition getPartialDefinition() { result = pd }
/**
* Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
* For instance, an update to a field of a struct containing only one field. For these cases we
* attach the PostUpdateNode to the store instruction. There's no obvious pre update node for this case
* (as the entire memory is updated), so `getPreUpdateNode` is implemented as `none()`.
*/
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
override StoreInstruction instr;
ExplicitSingleFieldStoreQualifierNode() {
not exists(ChiInstruction chi | chi.getPartial() = instr) and
// Without this condition any store would create a `PostUpdateNode`.
instr.getDestinationAddress() instanceof FieldAddressInstruction
}
override Node getPreUpdateNode() { none() }
override Expr getDefinedExpr() {
result =
instr
.getDestinationAddress()
.(FieldAddressInstruction)
.getObjectAddress()
.getUnconvertedResultExpression()
}
}
private FieldAddressInstruction getFieldInstruction(Instruction instr) {
result = instr or
result = instr.(CopyValueInstruction).getUnary()
}
/**
* The target of a `fieldStoreStepAfterArraySuppression` store step, which is used to convert
* an `ArrayContent` to a `FieldContent` when the `WriteSideEffect` instruction stores
* into a field. See the QLDoc for `suppressArrayRead` for an example of where such a conversion
* is inserted.
*/
private class WriteSideEffectFieldStoreQualifierNode extends PartialDefinitionNode {
override ChiInstruction instr;
WriteSideEffectInstruction write;
FieldAddressInstruction field;
WriteSideEffectFieldStoreQualifierNode() {
not instr.isResultConflated() and
instr.getPartial() = write and
field = getFieldInstruction(write.getDestinationAddress())
}
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
override Expr getDefinedExpr() {
result = field.getObjectAddress().getUnconvertedResultExpression()
}
override string toString() { result = getPreUpdateNode().toString() + " [post update]" }
}
/**
* The `PostUpdateNode` that is the target of a `arrayStoreStepChi` store step. The overriden
* `ChiInstruction` corresponds to the instruction represented by `node2` in `arrayStoreStepChi`.
*/
private class ArrayStoreNode extends PartialDefinitionNode {
override ChiInstruction instr;
private class ArrayStoreNode extends InstructionNode, PartialDefinition {
ChiInstruction chi;
PointerAddInstruction add;
ArrayStoreNode() {
not instr.isResultConflated() and
chi = this.getInstruction() and
not chi.isResultConflated() and
exists(StoreInstruction store |
instr.getPartial() = store and
chi.getPartial() = store and
add = store.getDestinationAddress()
)
}
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
override Node getPreUpdateNode() { result.asOperand() = chi.getTotalOperand() }
override Expr getDefinedExpr() { result = add.getLeft().getUnconvertedResultExpression() }
}
@@ -441,18 +532,24 @@ private class ArrayStoreNode extends PartialDefinitionNode {
* The `PostUpdateNode` that is the target of a `arrayStoreStepChi` store step. The overriden
* `ChiInstruction` corresponds to the instruction represented by `node2` in `arrayStoreStepChi`.
*/
private class PointerStoreNode extends PostUpdateNode {
override ChiInstruction instr;
private class PointerStoreNode extends InstructionNode, PartialDefinition {
ChiInstruction chi;
LoadInstruction load;
PointerStoreNode() {
not instr.isResultConflated() and
chi = this.getInstruction() and
not chi.isResultConflated() and
exists(StoreInstruction store |
instr.getPartial() = store and
store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction
chi.getPartial() = store and
load = store.getDestinationAddress().(CopyValueInstruction).getUnary()
)
}
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
override Node getPreUpdateNode() { result.asOperand() = chi.getTotalOperand() }
override Expr getDefinedExpr() {
result = load.getSourceAddress().getUnconvertedResultExpression()
}
}
/**
@@ -465,7 +562,7 @@ private class PointerStoreNode extends PostUpdateNode {
* returned. This node will have its `getArgument()` equal to `&x` and its
* `getVariableAccess()` equal to `x`.
*/
class DefinitionByReferenceNode extends InstructionNode {
class DefinitionByReferenceNode extends InstructionNode, PostUpdateNode {
override WriteSideEffectInstruction instr;
/** Gets the unconverted argument corresponding to this node. */
@@ -493,6 +590,22 @@ class DefinitionByReferenceNode extends InstructionNode {
not exists(instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget()) and
result = "output argument"
}
override Function getFunction() { result = instr.getEnclosingFunction() }
override IRType getType() { result = instr.getResultIRType() }
override Location getLocation() { result = instr.getLocation() }
// Make the read side effect's side effect operand the pre update node of this write side effect.
// This ensures that we match up the parameter index of the parameter indirection's modification.
override Node getPreUpdateNode() {
exists(ReadSideEffectInstruction read |
read.getPrimaryInstruction() = instr.getPrimaryInstruction() and
read.getArgumentDef() = instr.getDestinationAddress() and
result.asOperand() = read.getSideEffectOperand()
)
}
}
/**
@@ -510,15 +623,6 @@ class VariableNode extends Node, TVariableNode {
override Function getFunction() { none() }
override Declaration getEnclosingCallable() {
// When flow crosses from one _enclosing callable_ to another, the
// interprocedural data-flow library discards call contexts and inserts a
// node in the big-step relation used for human-readable path explanations.
// Therefore we want a distinct enclosing callable for each `VariableNode`,
// and that can be the `Variable` itself.
result = v
}
override IRType getType() { result.getCanonicalLanguageType().hasUnspecifiedType(v.getType(), _) }
override Location getLocation() { result = v.getLocation() }
@@ -585,6 +689,69 @@ Node uninitializedNode(LocalVariable v) { none() }
*/
predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) }
private predicate flowOutOfPostUpdate(PartialDefinitionNode nodeFrom, Node nodeTo) {
// flow from the "outermost" field to the `ChiInstruction`, or `StoreInstruction`
// if no `ChiInstruction` exists.
exists(AddressOperand addressOperand, PartialFieldDefinition pd |
pd = nodeFrom.getPartialDefinition() and
not exists(pd.getPreUpdateNode().getObjectNode()) and
pd.getPreUpdateNode().getNextNode*() = GetFieldNode::fromOperand(addressOperand) and
(
exists(ChiInstruction chi |
nodeTo.asInstruction() = chi and
chi.getPartial().getAnOperand() = addressOperand
)
or
exists(StoreInstruction store |
not exists(ChiInstruction chi | chi.getPartial() = store) and
nodeTo.asInstruction() = store and
store.getDestinationAddressOperand() = addressOperand
)
)
)
or
// Note: This partial definition cannot be a `PostUpdateFieldNode` since these nodes do not have an
// operand node as their pre update node.
exists(PartialDefinition pd |
pd = nodeFrom.getPartialDefinition() and
nodeTo.asInstruction().(ChiInstruction).getTotalOperand() = pd.getPreUpdateNode().asOperand()
)
}
/**
* Gets the `FieldNode` corresponding to the outermost field that is used to compute `address`.
*/
private FieldNode getOutermostFieldNode(Instruction address) {
not exists(result.getObjectNode()) and
result.getNextNode*() = GetFieldNode::fromInstruction(address)
}
private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) {
// flow from the memory of a load to the "outermost" field of that load.
exists(LoadInstruction load |
nodeTo = getOutermostFieldNode(load.getSourceAddress()) and
not nodeFrom.asInstruction().isResultConflated() and
nodeFrom.asInstruction() = load.getSourceValueOperand().getAnyDef()
)
or
// We need this to make stores look like loads for the dataflow library. So when there's a store
// of the form x->y = z we need to make the field node corresponding to y look like it's reading
// from the memory of x.
exists(StoreInstruction store, ChiInstruction chi |
chi.getPartial() = store and
nodeTo = getOutermostFieldNode(store.getDestinationAddress()) and
not nodeFrom.asInstruction().isResultConflated() and
nodeFrom.asInstruction() = chi.getTotal()
)
or
exists(ReadSideEffectInstruction read, SideEffectOperand sideEffect |
sideEffect = read.getSideEffectOperand() and
not sideEffect.getAnyDef().isResultConflated() and
nodeTo = getOutermostFieldNode(read.getArgumentDef()) and
nodeFrom.asOperand() = sideEffect
)
}
/**
* INTERNAL: do not use.
*
@@ -598,6 +765,10 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
or
// Instruction -> Operand flow
simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand())
or
flowIntoReadNode(nodeFrom, nodeTo)
or
flowOutOfPostUpdate(nodeFrom, nodeTo)
}
pragma[noinline]
@@ -749,6 +920,27 @@ private predicate modelFlow(Operand opFrom, Instruction iTo) {
)
)
)
or
impliedModelFlow(opFrom, iTo)
}
/**
* When a `DataFlowFunction` specifies dataflow from a parameter `p` to the return value there should
* also be dataflow from the parameter dereference (i.e., `*p`) to the return value dereference.
*/
private predicate impliedModelFlow(Operand opFrom, Instruction iTo) {
exists(
CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut,
int index
|
call.getStaticCallTarget() = func and
func.hasDataFlow(modelIn, modelOut)
|
modelIn.isParameterOrQualifierAddress(index) and
modelOut.isReturnValue() and
opFrom = getSideEffectFor(call, index).(ReadSideEffectInstruction).getSideEffectOperand() and
iTo = call // TODO: Add write side effects for return values
)
}
/**

View File

@@ -341,7 +341,7 @@ module IRTypeConsistency {
query predicate multipleIRTypes(Language::LanguageType type, string message) {
strictcount(type.getIRType()) > 1 and
message =
"`LanguageType` " + type.getAQlClass() + " has multiple `IRType`s: " +
"`LanguageType` " + type + " has multiple `IRType`s: " +
concat(type.getIRType().toString(), ", ")
}

View File

@@ -6,6 +6,7 @@
import semmle.code.cpp.Function
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Taint
@@ -13,27 +14,29 @@ import semmle.code.cpp.models.interfaces.Taint
* The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant
* `__builtin___memcpy_chk`.
*/
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction {
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction,
AliasFunction {
MemcpyFunction() {
// memcpy(dest, src, num)
// memmove(dest, src, num)
// memmove(dest, src, num, remaining)
this.hasName(["memcpy", "memmove", "__builtin___memcpy_chk"])
this.hasGlobalOrStdName(["memcpy", "memmove"])
or
// bcopy(src, dest, num)
this.hasGlobalOrStdName("bcopy")
// mempcpy(dest, src, num)
this.hasGlobalName(["bcopy", mempcpy(), "__builtin___memcpy_chk"])
}
/**
* Gets the index of the parameter that is the source buffer for the copy.
*/
int getParamSrc() { if this.hasGlobalOrStdName("bcopy") then result = 0 else result = 1 }
int getParamSrc() { if this.hasGlobalName("bcopy") then result = 0 else result = 1 }
/**
* Gets the index of the parameter that is the destination buffer for the
* copy.
*/
int getParamDest() { if this.hasGlobalOrStdName("bcopy") then result = 1 else result = 0 }
int getParamDest() { if this.hasGlobalName("bcopy") then result = 1 else result = 0 }
/**
* Gets the index of the parameter that is the size of the copy (in bytes).
@@ -82,4 +85,21 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect
i = getParamSrc()
)
}
override predicate parameterNeverEscapes(int index) {
index = getParamSrc()
or
this.hasGlobalName("bcopy") and index = getParamDest()
}
override predicate parameterEscapesOnlyViaReturn(int index) {
not this.hasGlobalName("bcopy") and index = getParamDest()
}
override predicate parameterIsAlwaysReturned(int index) {
not this.hasGlobalName(["bcopy", mempcpy()]) and
index = getParamDest()
}
}
private string mempcpy() { result = ["mempcpy", "wmempcpy"] }

View File

@@ -9,9 +9,9 @@ import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.DataFlow
/**
* The `std::basic_string` template class.
* The `std::basic_string` template class instantiations.
*/
private class StdBasicString extends TemplateClass {
private class StdBasicString extends ClassTemplateInstantiation {
StdBasicString() { this.hasQualifiedName("std", "basic_string") }
}
@@ -24,7 +24,7 @@ private class StdBasicString extends TemplateClass {
* ```
*/
private class StdStringConstructor extends Constructor, TaintFunction {
StdStringConstructor() { this.getDeclaringType().hasQualifiedName("std", "basic_string") }
StdStringConstructor() { this.getDeclaringType() instanceof StdBasicString }
/**
* Gets the index of a parameter to this function that is a string (or
@@ -69,7 +69,7 @@ private class StdStringConstructor extends Constructor, TaintFunction {
* The `std::string` function `c_str`.
*/
private class StdStringCStr extends TaintFunction {
StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") }
StdStringCStr() { this.getClassAndName("c_str") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from string itself (qualifier) to return value
@@ -82,7 +82,7 @@ private class StdStringCStr extends TaintFunction {
* The `std::string` function `data`.
*/
private class StdStringData extends TaintFunction {
StdStringData() { this.hasQualifiedName("std", "basic_string", "data") }
StdStringData() { this.getClassAndName("data") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from string itself (qualifier) to return value
@@ -100,7 +100,7 @@ private class StdStringData extends TaintFunction {
* The `std::string` function `push_back`.
*/
private class StdStringPush extends TaintFunction {
StdStringPush() { this.hasQualifiedName("std", "basic_string", "push_back") }
StdStringPush() { this.getClassAndName("push_back") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to qualifier
@@ -113,7 +113,7 @@ private class StdStringPush extends TaintFunction {
* The `std::string` functions `front` and `back`.
*/
private class StdStringFrontBack extends TaintFunction {
StdStringFrontBack() { this.hasQualifiedName("std", "basic_string", ["front", "back"]) }
StdStringFrontBack() { this.getClassAndName(["front", "back"]) instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from object to returned reference
@@ -123,12 +123,12 @@ private class StdStringFrontBack extends TaintFunction {
}
/**
* The `std::string` function `operator+`.
* The (non-member) `std::string` function `operator+`.
*/
private class StdStringPlus extends TaintFunction {
StdStringPlus() {
this.hasQualifiedName("std", "operator+") and
this.getUnspecifiedType() = any(StdBasicString s).getAnInstantiation()
this.getUnspecifiedType() instanceof StdBasicString
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -148,7 +148,7 @@ private class StdStringPlus extends TaintFunction {
*/
private class StdStringAppend extends TaintFunction {
StdStringAppend() {
this.hasQualifiedName("std", "basic_string", ["operator+=", "append", "insert", "replace"])
this.getClassAndName(["operator+=", "append", "insert", "replace"]) instanceof StdBasicString
}
/**
@@ -190,7 +190,7 @@ private class StdStringAppend extends TaintFunction {
* The standard function `std::string.assign`.
*/
private class StdStringAssign extends TaintFunction {
StdStringAssign() { this.hasQualifiedName("std", "basic_string", "assign") }
StdStringAssign() { this.getClassAndName("assign") instanceof StdBasicString }
/**
* Gets the index of a parameter to this function that is a string (or
@@ -230,7 +230,7 @@ private class StdStringAssign extends TaintFunction {
* The standard function `std::string.copy`.
*/
private class StdStringCopy extends TaintFunction {
StdStringCopy() { this.hasQualifiedName("std", "basic_string", "copy") }
StdStringCopy() { this.getClassAndName("copy") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// copy(dest, num, pos)
@@ -243,7 +243,7 @@ private class StdStringCopy extends TaintFunction {
* The standard function `std::string.substr`.
*/
private class StdStringSubstr extends TaintFunction {
StdStringSubstr() { this.hasQualifiedName("std", "basic_string", "substr") }
StdStringSubstr() { this.getClassAndName("substr") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// substr(pos, num)
@@ -252,11 +252,18 @@ private class StdStringSubstr extends TaintFunction {
}
}
/**
* The `std::basic_stringstream` template class instantiations.
*/
private class StdBasicStringStream extends ClassTemplateInstantiation {
StdBasicStringStream() { this.hasQualifiedName("std", "basic_stringstream") }
}
/**
* The `std::string` functions `at` and `operator[]`.
*/
private class StdStringAt extends TaintFunction {
StdStringAt() { this.hasQualifiedName("std", "basic_string", ["at", "operator[]"]) }
StdStringAt() { this.getClassAndName(["at", "operator[]"]) instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to referenced return value
@@ -270,9 +277,9 @@ private class StdStringAt extends TaintFunction {
}
/**
* The `std::basic_istream` template class.
* The `std::basic_istream` template class instantiations.
*/
private class StdBasicIStream extends TemplateClass {
private class StdBasicIStream extends ClassTemplateInstantiation {
StdBasicIStream() { this.hasQualifiedName("std", "basic_istream") }
}
@@ -280,7 +287,7 @@ private class StdBasicIStream extends TemplateClass {
* The `std::istream` function `operator>>` (defined as a member function).
*/
private class StdIStreamIn extends DataFlowFunction, TaintFunction {
StdIStreamIn() { this.hasQualifiedName("std", "basic_istream", "operator>>") }
StdIStreamIn() { this.getClassAndName("operator>>") instanceof StdBasicIStream }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// returns reference to `*this`
@@ -305,8 +312,7 @@ private class StdIStreamIn extends DataFlowFunction, TaintFunction {
private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
StdIStreamInNonMember() {
this.hasQualifiedName("std", "operator>>") and
this.getUnspecifiedType().(ReferenceType).getBaseType() =
any(StdBasicIStream s).getAnInstantiation()
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicIStream
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
@@ -331,7 +337,7 @@ private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
*/
private class StdIStreamGet extends TaintFunction {
StdIStreamGet() {
this.hasQualifiedName("std", "basic_istream", ["get", "peek"]) and
this.getClassAndName(["get", "peek"]) instanceof StdBasicIStream and
this.getNumberOfParameters() = 0
}
@@ -347,7 +353,7 @@ private class StdIStreamGet extends TaintFunction {
*/
private class StdIStreamRead extends DataFlowFunction, TaintFunction {
StdIStreamRead() {
this.hasQualifiedName("std", "basic_istream", ["get", "read"]) and
this.getClassAndName(["get", "read"]) instanceof StdBasicIStream and
this.getNumberOfParameters() > 0
}
@@ -372,7 +378,7 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction {
* The `std::istream` function `readsome`.
*/
private class StdIStreamReadSome extends TaintFunction {
StdIStreamReadSome() { this.hasQualifiedName("std", "basic_istream", "readsome") }
StdIStreamReadSome() { this.getClassAndName("readsome") instanceof StdBasicIStream }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to first parameter
@@ -385,7 +391,7 @@ private class StdIStreamReadSome extends TaintFunction {
* The `std::istream` function `putback`.
*/
private class StdIStreamPutBack extends DataFlowFunction, TaintFunction {
StdIStreamPutBack() { this.hasQualifiedName("std", "basic_istream", "putback") }
StdIStreamPutBack() { this.getClassAndName("putback") instanceof StdBasicIStream }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// returns reference to `*this`
@@ -418,7 +424,7 @@ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction {
* The `std::istream` function `getline`.
*/
private class StdIStreamGetLine extends DataFlowFunction, TaintFunction {
StdIStreamGetLine() { this.hasQualifiedName("std", "basic_istream", "getline") }
StdIStreamGetLine() { this.getClassAndName("getline") instanceof StdBasicIStream }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// returns reference to `*this`
@@ -461,9 +467,9 @@ private class StdGetLine extends DataFlowFunction, TaintFunction {
}
/**
* The `std::basic_ostream` template class.
* The `std::basic_ostream` template class instantiations.
*/
private class StdBasicOStream extends TemplateClass {
private class StdBasicOStream extends ClassTemplateInstantiation {
StdBasicOStream() { this.hasQualifiedName("std", "basic_ostream") }
}
@@ -472,7 +478,9 @@ private class StdBasicOStream extends TemplateClass {
* `put` and `write`.
*/
private class StdOStreamOut extends DataFlowFunction, TaintFunction {
StdOStreamOut() { this.hasQualifiedName("std", "basic_ostream", ["operator<<", "put", "write"]) }
StdOStreamOut() {
this.getClassAndName(["operator<<", "put", "write"]) instanceof StdBasicOStream
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// returns reference to `*this`
@@ -507,8 +515,7 @@ private class StdOStreamOut extends DataFlowFunction, TaintFunction {
private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
StdOStreamOutNonMember() {
this.hasQualifiedName("std", "operator<<") and
this.getUnspecifiedType().(ReferenceType).getBaseType() =
any(StdBasicOStream s).getAnInstantiation()
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicOStream
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
@@ -537,9 +544,7 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
* input parameter.
*/
private class StdStringStreamConstructor extends Constructor, TaintFunction {
StdStringStreamConstructor() {
this.getDeclaringType().hasQualifiedName("std", "basic_stringstream")
}
StdStringStreamConstructor() { this.getDeclaringType() instanceof StdBasicStringStream }
/**
* Gets the index of a parameter to this function that is a string.
@@ -563,7 +568,7 @@ private class StdStringStreamConstructor extends Constructor, TaintFunction {
* The `std::stringstream` function `str`.
*/
private class StdStringStreamStr extends TaintFunction {
StdStringStreamStr() { this.hasQualifiedName("std", "basic_stringstream", "str") }
StdStringStreamStr() { this.getClassAndName("str") instanceof StdBasicStringStream }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to return value (if any)
@@ -576,15 +581,24 @@ private class StdStringStreamStr extends TaintFunction {
}
}
/**
* The `std::basic_ios` template class instantiations.
*/
private class StdBasicIOS extends ClassTemplateInstantiation {
StdBasicIOS() { this.hasQualifiedName("std", "basic_ios") }
}
/**
* A `std::` stream function that does not require a model, except that it
* returns a reference to `*this` and thus could be used in a chain.
*/
private class StdStreamFunction extends DataFlowFunction, TaintFunction {
StdStreamFunction() {
this.hasQualifiedName("std", "basic_istream", ["ignore", "unget", "seekg"]) or
this.hasQualifiedName("std", "basic_ostream", ["seekp", "flush"]) or
this.hasQualifiedName("std", "basic_ios", "copyfmt")
this.getClassAndName(["ignore", "unget", "seekg"]) instanceof StdBasicIStream
or
this.getClassAndName(["seekp", "flush"]) instanceof StdBasicOStream
or
this.getClassAndName("copyfmt") instanceof StdBasicIOS
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {

View File

@@ -40,9 +40,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid
/**
* Holds if this is one of the `strcpy_s` variants.
*/
private predicate isSVariant() {
exists(string name | name = getName() | name.suffix(name.length() - 2) = "_s")
}
private predicate isSVariant() { getName().matches("%\\_s") }
/**
* Gets the index of the parameter that is the maximum size of the copy (in characters).

View File

@@ -24,5 +24,6 @@ abstract class DataFlowFunction extends Function {
* represented by `input` to the return value or buffer represented by
* `output`
*/
pragma[nomagic]
abstract predicate hasDataFlow(FunctionInput input, FunctionOutput output);
}

View File

@@ -108,6 +108,16 @@ class FunctionInput extends TFunctionInput {
*/
predicate isQualifierAddress() { none() }
/**
* Holds if `i >= 0` and `isParameter(i)` holds for this value, or
* if `i = -1` and `isQualifierAddress()` holds for this value.
*/
final predicate isParameterOrQualifierAddress(ParameterIndex i) {
i >= 0 and this.isParameter(i)
or
i = -1 and this.isQualifierAddress()
}
/**
* Holds if this is the input value pointed to by the return value of a
* function, if the function returns a pointer, or the input value referred
@@ -134,7 +144,7 @@ class FunctionInput extends TFunctionInput {
predicate isReturnValueDeref() { none() }
/**
* Holds if `i >= 0` and `isParameterDeref(i)` holds for this is value, or
* Holds if `i >= 0` and `isParameterDeref(i)` holds for this value, or
* if `i = -1` and `isQualifierObject()` holds for this value.
*/
final predicate isParameterDerefOrQualifierObject(ParameterIndex i) {

View File

@@ -28,5 +28,6 @@ abstract class TaintFunction extends Function {
* Holds if data passed into the argument, qualifier, or buffer represented by
* `input` influences the return value or buffer represented by `output`
*/
pragma[nomagic]
abstract predicate hasTaintFlow(FunctionInput input, FunctionOutput output);
}

View File

@@ -0,0 +1,3 @@
| test.c:13:9:13:13 | buff1 | This variable will not be cleared. |
| test.c:35:9:35:13 | buff1 | This variable will not be cleared. |
| test.c:43:9:43:13 | buff1 | This variable will not be cleared. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql

View File

@@ -0,0 +1,201 @@
struct buffers
{
unsigned char buff1[50];
unsigned char *buff2;
} globalBuff1,*globalBuff2;
unsigned char * globalBuff;
void badFunc0_0(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
}
void nobadFunc0_0(){
unsigned char buff1[12];
memset(buff1,12,12);
}
void nobadFunc0_1(){
unsigned char buff1[12];
int i;
memset(buff1,12,12);
for(i=0;i<12;i++)
buff1[i]=13;
free(buff1);
}
void nobadFunc1_0(){
unsigned char * buff1;
buff1 = (unsigned char *) malloc(12);
memset(buff1,12,12);
}
void badFunc1_0(){
unsigned char * buff1;
buff1 = (unsigned char *) malloc(12);
memset(buff1,12,12);
free(buff1);
}
void badFunc1_1(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
free(buff1);
}
void nobadFunc2_0_0(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
printf(buff1);
}
void nobadFunc2_0_1(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
printf(buff1+3);
}
void nobadFunc2_0_2(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
printf(*buff1);
}
void nobadFunc2_0_3(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
printf(*(buff1+3));
}
unsigned char * nobadFunc2_0_4(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
return buff1;
}
unsigned char * nobadFunc2_0_5(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
return buff1+3;
}
unsigned char nobadFunc2_0_6(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
return *buff1;
}
unsigned char nobadFunc2_0_7(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
return *(buff1+3);
}
void nobadFunc2_1_0(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
if(*buff1==0)
printf("123123");
}
void nobadFunc2_1_1(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
if(*(buff1+3)==0)
printf("123123");
}
void nobadFunc2_1_2(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
buff1[2]=5;
}
void nobadFunc3_0(unsigned char * buffAll){
unsigned char * buff1 = buffAll;
memset(buff1,12,12);
}
void nobadFunc3_1(unsigned char * buffAll){
unsigned char * buff1 = buffAll+3;
memset(buff1,12,12);
}
void nobadFunc3_2(struct buffers buffAll){
unsigned char * buff1 = buffAll.buff1;
memset(buff1,12,12);
}
void nobadFunc3_3(struct buffers buffAll){
unsigned char * buff1 = buffAll.buff2;
memset(buff1,12,12);
}
void nobadFunc3_4(struct buffers buffAll){
unsigned char * buff1 = buffAll.buff2+3;
memset(buff1,12,12);
}
void nobadFunc3_5(struct buffers * buffAll){
unsigned char * buff1 = buffAll->buff1;
memset(buff1,12,12);
}
void nobadFunc3_6(struct buffers *buffAll){
unsigned char * buff1 = buffAll->buff2;
memset(buff1,12,12);
}
void nobadFunc4(){
unsigned char * buff1 = globalBuff;
memset(buff1,12,12);
}
void nobadFunc4_0(){
unsigned char * buff1 = globalBuff;
memset(buff1,12,12);
}
void nobadFunc4_1(){
unsigned char * buff1 = globalBuff+3;
memset(buff1,12,12);
}
void nobadFunc4_2(){
unsigned char * buff1 = globalBuff1.buff1;
memset(buff1,12,12);
}
void nobadFunc4_3(){
unsigned char * buff1 = globalBuff1.buff2;
memset(buff1,12,12);
}
void nobadFunc4_4(){
unsigned char * buff1 = globalBuff1.buff2+3;
memset(buff1,12,12);
}
void nobadFunc4_5(){
unsigned char * buff1 = globalBuff2->buff1;
memset(buff1,12,12);
}
void nobadFunc4_6(){
unsigned char * buff1 = globalBuff2->buff2;
memset(buff1,12,12);
}

View File

@@ -13,9 +13,9 @@ nodes
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
| test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode |
#select
| test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:57:9:57:18 | theZipcode | this source. |
| test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@ | test.cpp:74:24:74:30 | medical | this source. |
| test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@ | test.cpp:77:16:77:22 | medical | this source. |
| test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@ | test.cpp:81:22:81:28 | medical | this source. |
| test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:96:37:96:46 | theZipcode | this source. |
| test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:99:42:99:51 | theZipcode | this source. |
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:57:9:57:18 | theZipcode | this source. |
| test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@ | test.cpp:74:24:74:30 | medical | this source. |
| test.cpp:78:24:78:27 | temp | test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@ | test.cpp:77:16:77:22 | medical | this source. |
| test.cpp:82:24:82:28 | buff5 | test.cpp:81:22:81:28 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@ | test.cpp:81:22:81:28 | medical | this source. |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:96:37:96:46 | theZipcode | this source. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:99:42:99:51 | theZipcode | this source. |

View File

@@ -2,3 +2,7 @@
| test.c:63:29:63:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:139:29:139:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:186:29:186:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:282:29:282:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:299:26:299:32 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:328:29:328:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:342:29:342:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |

View File

@@ -2,7 +2,7 @@
#define NULL ((void*)0)
#define assert(x) if (!(x)) __assert_fail(#x,__FILE__,__LINE__)
void __assert_fail(const char *assertion, const char *file, int line) { }
void __assert_fail(const char *assertion, const char *file, int line);
void aFakeFailed_1(int file, int line)
{
@@ -272,3 +272,75 @@ unsigned char * noBadResize_2_7(unsigned char * buffer,size_t currentSize,size_t
myASSERT_2(buffer);
return buffer;
}
unsigned char *goodResize_3_1(unsigned char *buffer, size_t currentSize, size_t newSize)
{
// GOOD: this way we will exclude possible memory leak [FALSE POSITIVE]
unsigned char *tmp = buffer;
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
if (buffer == NULL)
{
free(tmp);
return NULL;
}
}
return buffer;
}
unsigned char *goodResize_3_2(unsigned char *buffer, size_t currentSize, size_t newSize)
{
// GOOD: this way we will exclude possible memory leak [FALSE POSITIVE]
unsigned char *tmp = buffer;
if (currentSize < newSize)
{
tmp = (unsigned char *)realloc(tmp, newSize);
if (tmp != 0)
{
buffer = tmp;
}
}
return buffer;
}
void abort(void);
unsigned char *noBadResize_4_1(unsigned char *buffer, size_t currentSize, size_t newSize)
{
// GOOD: program to end
if (currentSize < newSize)
{
if (buffer = (unsigned char *)realloc(buffer, newSize))
abort();
}
return buffer;
}
unsigned char * badResize_5_2(unsigned char *buffer, size_t currentSize, size_t newSize, int cond)
{
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
}
if (cond)
{
abort(); // irrelevant
}
return buffer;
}
unsigned char * badResize_5_1(unsigned char *buffer, size_t currentSize, size_t newSize, int cond)
{
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
assert(cond); // irrelevant
}
return buffer;
}

View File

@@ -0,0 +1,3 @@
| test.c:4:3:4:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
| test.c:11:3:11:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
| test.c:19:3:19:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql

View File

@@ -0,0 +1,28 @@
void workFunction_0(char *s) {
char buf[80];
strncat(buf, s, sizeof(buf)-strlen(buf)-1); // GOOD
strncat(buf, s, sizeof(buf)-strlen(buf)); // BAD
strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD [NOT DETECTED]
}
void workFunction_1(char *s) {
#define MAX_SIZE 80
char buf[MAX_SIZE];
strncat(buf, s, MAX_SIZE-strlen(buf)-1); // GOOD
strncat(buf, s, MAX_SIZE-strlen(buf)); // BAD
strncat(buf, "fix", MAX_SIZE-strlen(buf)); // BAD [NOT DETECTED]
}
void workFunction_2_0(char *s) {
char * buf;
int len=80;
buf = (char *) malloc(len);
strncat(buf, s, len-strlen(buf)-1); // GOOD
strncat(buf, s, len-strlen(buf)); // BAD
strncat(buf, "fix", len-strlen(buf)); // BAD [NOT DETECTED]
}
void workFunction_2_1(char *s) {
char * buf;
int len=80;
buf = (char *) malloc(len+1);
strncat(buf, s, len-strlen(buf)-1); // GOOD
strncat(buf, s, len-strlen(buf)); // GOOD
}

View File

@@ -26,60 +26,21 @@ unreachableNodeCCtx
localCallNodes
postIsNotPre
postHasUniquePre
| dispatch.cpp:15:8:15:8 | Top output argument | PostUpdateNode should have one pre-update node but has 0. |
| dispatch.cpp:21:8:21:8 | Middle output argument | PostUpdateNode should have one pre-update node but has 0. |
| dispatch.cpp:60:18:60:29 | Bottom output argument | PostUpdateNode should have one pre-update node but has 0. |
| dispatch.cpp:61:18:61:29 | Middle output argument | PostUpdateNode should have one pre-update node but has 0. |
| dispatch.cpp:65:10:65:21 | Bottom output argument | PostUpdateNode should have one pre-update node but has 0. |
| test.cpp:384:10:384:13 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. |
| test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. |
| test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. |
| test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. |
uniquePostUpdate
postIsInSameCallable
reverseRead
argHasPostUpdate
postWithInFlow
| BarrierGuard.cpp:49:3:49:17 | Chi | PostUpdateNode should not be the target of local flow. |
| BarrierGuard.cpp:60:3:60:18 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:28:3:28:34 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:34:22:34:27 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:34:32:34:37 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:39:32:39:37 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:39:42:39:47 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:43:35:43:40 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:43:51:43:51 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:49:25:49:30 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:49:35:49:40 | Chi | PostUpdateNode should not be the target of local flow. |
| clang.cpp:50:3:50:26 | Chi | PostUpdateNode should not be the target of local flow. |
| example.c:17:19:17:22 | Chi | PostUpdateNode should not be the target of local flow. |
| example.c:17:21:17:21 | Chi | PostUpdateNode should not be the target of local flow. |
| example.c:24:2:24:30 | Chi | PostUpdateNode should not be the target of local flow. |
| example.c:24:13:24:30 | Chi | PostUpdateNode should not be the target of local flow. |
| example.c:26:2:26:25 | Chi | PostUpdateNode should not be the target of local flow. |
| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. |
| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. |
| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:13:12:13:12 | Chi | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:13:15:13:15 | Chi | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:28:10:31:2 | Chi | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:28:10:31:2 | Chi | PostUpdateNode should not be the target of local flow. |
| lambdas.cpp:43:3:43:14 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:11:5:11:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:20:5:20:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:22:7:22:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:24:7:24:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:29:5:29:18 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:31:7:31:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:39:7:39:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:44:5:44:18 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:46:7:46:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:48:7:48:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:75:5:75:17 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:83:5:83:17 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:87:7:87:17 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:89:7:89:17 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:94:5:94:22 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:96:7:96:17 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:104:7:104:17 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:109:5:109:22 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:113:7:113:17 | Chi | PostUpdateNode should not be the target of local flow. |
| ref.cpp:115:7:115:17 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:91:3:91:18 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:115:3:115:17 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:120:3:120:10 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:125:3:125:11 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:359:5:359:20 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:373:5:373:20 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:465:3:465:15 | Chi | PostUpdateNode should not be the target of local flow. |
| test.cpp:384:10:384:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
| test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
| test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
| test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |

View File

@@ -362,7 +362,7 @@ class FlowThroughFields {
int f() {
sink(field); // tainted or clean? Not sure.
taintField();
sink(field); // $ ast MISSING: ir
sink(field); // $ ast,ir
}
int calledAfterTaint() {

View File

@@ -204,4 +204,32 @@ void deep_member_field_arrow(S2 *ps2) {
void deep_member_field_arrow_different_fields(S2 *ps2) {
taint_a_ptr(&ps2->s.m1);
sink(ps2->s.m2);
}
void test_deep_struct_fields() {
S2 s2;
s2.s.m1 = user_input();
S s = s2.s;
sink(s.m1); // $ ast,ir
}
void test_deep_struct_fields_no_flow() {
S2 s2;
s2.s.m1 = user_input();
S s = s2.s;
sink(s.m2);
}
void test_deep_struct_fields_taint_through_call() {
S2 s2;
taint_a_ptr(&s2.s.m1);
S s = s2.s;
sink(s.m1); // $ ast,ir
}
void test_deep_struct_fields_taint_through_call_no_flow() {
S2 s2;
taint_a_ptr(&s2.s.m1);
S s = s2.s;
sink(s.m2);
}

View File

@@ -1,4 +1,4 @@
void sink(void *o);
void sink(void *o); void sink(const char *o);
void *user_input(void);
struct S {
@@ -135,3 +135,13 @@ void test_outer_with_ref(Outer *pouter) {
sink(pouter->inner_ptr->a); // $ ast MISSING: ir
sink(pouter->a); // $ ast,ir
}
void taint_a_ptr(const char **pa) {
*pa = (char*)user_input();
}
void test_const_char_ref() {
const char* s;
taint_a_ptr(&s);
sink(s); // $ ast ir=140:9 ir=140:16
}

View File

@@ -89,6 +89,10 @@ postWithInFlow
| aliasing.cpp:194:21:194:22 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:200:23:200:24 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:205:23:205:24 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:211:8:211:9 | m1 [post update] | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:218:8:218:9 | m1 [post update] | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:225:21:225:22 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:232:21:232:22 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:6:3:6:5 | arr [inner post update] | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:6:3:6:8 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:15:3:15:10 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
@@ -119,6 +123,9 @@ postWithInFlow
| by_reference.cpp:108:24:108:24 | a [inner post update] | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:123:28:123:36 | inner_ptr [inner post update] | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:127:30:127:38 | inner_ptr [inner post update] | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:140:3:140:5 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:140:4:140:5 | pa [inner post update] | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:145:16:145:16 | s [inner post update] | PostUpdateNode should not be the target of local flow. |
| complex.cpp:11:22:11:23 | a_ [post update] | PostUpdateNode should not be the target of local flow. |
| complex.cpp:12:22:12:23 | b_ [post update] | PostUpdateNode should not be the target of local flow. |
| conflated.cpp:10:3:10:7 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
@@ -152,5 +159,6 @@ postWithInFlow
| simple.cpp:65:7:65:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:83:12:83:13 | f1 [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
| simple.cpp:104:9:104:9 | i [post update] | PostUpdateNode should not be the target of local flow. |
| struct_init.c:24:11:24:12 | ab [inner post update] | PostUpdateNode should not be the target of local flow. |
| struct_init.c:36:17:36:24 | nestedAB [inner post update] | PostUpdateNode should not be the target of local flow. |

View File

@@ -20,145 +20,71 @@ unreachableNodeCCtx
localCallNodes
postIsNotPre
postHasUniquePre
| simple.cpp:65:5:65:22 | Store | PostUpdateNode should have one pre-update node but has 0. |
| simple.cpp:92:5:92:22 | Store | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:9:9:9:9 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:14:9:14:9 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:31:14:31:21 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:38:7:38:8 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:39:7:39:8 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:41:15:41:21 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:47:12:47:18 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:54:12:54:18 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:55:12:55:19 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:57:11:57:24 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:57:17:57:23 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:62:13:62:19 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:64:21:64:28 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:71:13:71:19 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:73:25:73:32 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:89:15:89:21 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:99:14:99:21 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:116:12:116:19 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:126:12:126:18 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:130:12:130:18 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:142:14:142:20 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:143:25:143:31 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:150:12:150:18 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:151:12:151:24 | D output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:159:12:159:18 | B output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:160:18:160:60 | MyList output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:160:32:160:59 | MyList output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:161:18:161:40 | MyList output argument | PostUpdateNode should have one pre-update node but has 0. |
| A.cpp:162:18:162:40 | MyList output argument | PostUpdateNode should have one pre-update node but has 0. |
| B.cpp:7:16:7:35 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| B.cpp:8:16:8:27 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| B.cpp:16:16:16:38 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| B.cpp:17:16:17:27 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| C.cpp:18:12:18:18 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:29:15:29:41 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:29:24:29:40 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:36:15:36:41 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:36:24:36:40 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:43:15:43:41 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:43:24:43:40 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:50:15:50:41 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:50:24:50:40 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:57:16:57:42 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| D.cpp:57:25:57:41 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| complex.cpp:22:11:22:17 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
| complex.cpp:25:7:25:7 | Bar output argument | PostUpdateNode should have one pre-update node but has 0. |
| complex.cpp:48:9:48:10 | Outer output argument | PostUpdateNode should have one pre-update node but has 0. |
| complex.cpp:49:9:49:10 | Outer output argument | PostUpdateNode should have one pre-update node but has 0. |
| complex.cpp:50:9:50:10 | Outer output argument | PostUpdateNode should have one pre-update node but has 0. |
| complex.cpp:51:9:51:10 | Outer output argument | PostUpdateNode should have one pre-update node but has 0. |
| conflated.cpp:59:20:59:39 | LinkedList output argument | PostUpdateNode should have one pre-update node but has 0. |
| constructors.cpp:34:11:34:26 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
| constructors.cpp:35:11:35:26 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
| constructors.cpp:36:11:36:37 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
| constructors.cpp:37:11:37:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. |
| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. |
| simple.cpp:34:11:34:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
| simple.cpp:35:11:35:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
| simple.cpp:36:11:36:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
| simple.cpp:37:11:37:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
uniquePostUpdate
postIsInSameCallable
reverseRead
argHasPostUpdate
postWithInFlow
| A.cpp:25:7:25:17 | Chi | PostUpdateNode should not be the target of local flow. |
| A.cpp:27:22:27:32 | Chi | PostUpdateNode should not be the target of local flow. |
| A.cpp:98:12:98:18 | Chi | PostUpdateNode should not be the target of local flow. |
| A.cpp:100:5:100:13 | Chi | PostUpdateNode should not be the target of local flow. |
| A.cpp:142:7:142:20 | Chi | PostUpdateNode should not be the target of local flow. |
| A.cpp:143:7:143:31 | Chi | PostUpdateNode should not be the target of local flow. |
| A.cpp:183:7:183:20 | Chi | PostUpdateNode should not be the target of local flow. |
| A.cpp:184:7:184:23 | Chi | PostUpdateNode should not be the target of local flow. |
| B.cpp:6:15:6:24 | Chi | PostUpdateNode should not be the target of local flow. |
| B.cpp:15:15:15:27 | Chi | PostUpdateNode should not be the target of local flow. |
| B.cpp:35:7:35:22 | Chi | PostUpdateNode should not be the target of local flow. |
| B.cpp:36:7:36:22 | Chi | PostUpdateNode should not be the target of local flow. |
| B.cpp:46:7:46:21 | Chi | PostUpdateNode should not be the target of local flow. |
| C.cpp:22:12:22:21 | Chi | PostUpdateNode should not be the target of local flow. |
| C.cpp:22:12:22:21 | Chi | PostUpdateNode should not be the target of local flow. |
| C.cpp:24:5:24:25 | Chi | PostUpdateNode should not be the target of local flow. |
| C.cpp:24:16:24:25 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:9:21:9:28 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:11:29:11:36 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:16:21:16:27 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:18:29:18:35 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:28:15:28:24 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:35:15:35:24 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:42:15:42:24 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:49:15:49:24 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:56:15:56:24 | Chi | PostUpdateNode should not be the target of local flow. |
| D.cpp:57:5:57:42 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:9:3:9:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:13:3:13:21 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:17:3:17:21 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:21:12:21:12 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:21:15:21:15 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:22:12:22:12 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:22:15:22:15 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:23:12:23:12 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:23:15:23:15 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:35:12:35:12 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:35:15:35:15 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:37:3:37:24 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:40:12:40:12 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:40:15:40:15 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:42:3:42:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:47:12:47:12 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:47:15:47:15 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:49:3:49:25 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:52:12:52:12 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:52:15:52:15 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:54:3:54:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:59:12:59:12 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:59:15:59:15 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:60:3:60:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:70:19:70:19 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:70:22:70:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:72:3:72:21 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:77:19:77:19 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:77:22:77:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:79:3:79:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:84:19:84:19 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:84:22:84:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:86:3:86:21 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:91:19:91:19 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:91:22:91:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:92:3:92:23 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:98:3:98:21 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:106:3:106:20 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:111:15:111:19 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:147:15:147:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:175:15:175:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:181:15:181:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:187:15:187:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:194:15:194:22 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:200:15:200:24 | Chi | PostUpdateNode should not be the target of local flow. |
| aliasing.cpp:205:15:205:24 | Chi | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:5:18:5:23 | Chi | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:5:21:5:21 | Chi | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:6:3:6:23 | Chi | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:14:18:14:23 | Chi | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:14:21:14:21 | Chi | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:15:3:15:25 | Chi | PostUpdateNode should not be the target of local flow. |
| arrays.cpp:36:3:36:37 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:12:5:12:16 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:16:5:16:19 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:84:3:84:25 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:88:3:88:24 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:92:3:92:20 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:96:3:96:19 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:102:21:102:39 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:104:15:104:22 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:106:21:106:41 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:108:15:108:24 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:122:21:122:38 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:124:15:124:21 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:126:21:126:40 | Chi | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:128:15:128:23 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:11:22:11:27 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:12:22:12:27 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:14:26:14:26 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:14:33:14:33 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:22:11:22:17 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:25:7:25:7 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:42:16:42:16 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:43:16:43:16 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:53:12:53:12 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:54:12:54:12 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:55:12:55:12 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:56:12:56:12 | Chi | PostUpdateNode should not be the target of local flow. |
| conflated.cpp:45:39:45:42 | Chi | PostUpdateNode should not be the target of local flow. |
| conflated.cpp:53:3:53:27 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:20:24:20:29 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:21:24:21:29 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:23:28:23:28 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:23:35:23:35 | Chi | PostUpdateNode should not be the target of local flow. |
| qualifiers.cpp:9:30:9:44 | Chi | PostUpdateNode should not be the target of local flow. |
| qualifiers.cpp:12:49:12:64 | Chi | PostUpdateNode should not be the target of local flow. |
| qualifiers.cpp:13:51:13:65 | Chi | PostUpdateNode should not be the target of local flow. |
| realistic.cpp:39:12:39:95 | Chi | PostUpdateNode should not be the target of local flow. |
| realistic.cpp:49:9:49:64 | Chi | PostUpdateNode should not be the target of local flow. |
| simple.cpp:20:24:20:29 | Chi | PostUpdateNode should not be the target of local flow. |
| simple.cpp:21:24:21:29 | Chi | PostUpdateNode should not be the target of local flow. |
| simple.cpp:23:28:23:28 | Chi | PostUpdateNode should not be the target of local flow. |
| simple.cpp:23:35:23:35 | Chi | PostUpdateNode should not be the target of local flow. |
| simple.cpp:65:5:65:22 | Store | PostUpdateNode should not be the target of local flow. |
| simple.cpp:83:9:83:28 | Chi | PostUpdateNode should not be the target of local flow. |
| simple.cpp:92:5:92:22 | Store | PostUpdateNode should not be the target of local flow. |
| struct_init.c:20:20:20:29 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:20:34:20:34 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:27:7:27:16 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:27:21:27:21 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:28:5:28:7 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:36:10:36:24 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:40:20:40:29 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:40:34:40:34 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:42:7:42:16 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:42:21:42:21 | Chi | PostUpdateNode should not be the target of local flow. |
| struct_init.c:43:5:43:7 | Chi | PostUpdateNode should not be the target of local flow. |
| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should not be the target of local flow. |

View File

@@ -4,50 +4,62 @@ edges
| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | set output argument [c] |
| A.cpp:57:11:57:24 | B output argument [c] | A.cpp:57:28:57:30 | call to get |
| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | B output argument [c] |
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Chi [a] |
| A.cpp:100:5:100:13 | Chi [a] | A.cpp:103:14:103:14 | *c [a] |
| A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a |
| A.cpp:98:12:98:18 | new | A.cpp:100:9:100:9 | a [post update] [a] |
| A.cpp:100:9:100:9 | a [post update] [a] | A.cpp:103:14:103:14 | *c [a] |
| A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a [a] |
| A.cpp:107:16:107:16 | a [a] | A.cpp:107:16:107:16 | a |
| A.cpp:126:5:126:5 | Chi [c] | A.cpp:131:8:131:8 | f7 output argument [c] |
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:126:5:126:5 | Chi [c] |
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:131:8:131:8 | f7 output argument [c] |
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | set output argument [c] |
| A.cpp:131:8:131:8 | Chi [c] | A.cpp:132:13:132:13 | c |
| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:131:8:131:8 | Chi [c] |
| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:132:13:132:13 | c [c] |
| A.cpp:132:13:132:13 | c [c] | A.cpp:132:13:132:13 | c |
| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:142:10:142:10 | c [post update] [c] | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:142:10:142:10 | c [post update] [c] | A.cpp:151:18:151:18 | D output argument [c] |
| A.cpp:142:14:142:20 | new | A.cpp:142:10:142:10 | c [post update] [c] |
| A.cpp:143:7:143:31 | Chi [b] | A.cpp:151:12:151:24 | D output argument [b] |
| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | Chi [b] |
| A.cpp:143:13:143:13 | b [post update] [b] | A.cpp:143:7:143:31 | Chi [b] |
| A.cpp:143:25:143:31 | new | A.cpp:143:13:143:13 | b [post update] [b] |
| A.cpp:150:12:150:18 | new | A.cpp:151:12:151:24 | D output argument [b] |
| A.cpp:151:12:151:24 | Chi [b] | A.cpp:152:13:152:13 | b |
| A.cpp:151:12:151:24 | D output argument [b] | A.cpp:151:12:151:24 | Chi [b] |
| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c |
| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] |
| A.cpp:151:12:151:24 | D output argument [b] | A.cpp:152:13:152:13 | b [b] |
| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:154:13:154:13 | c [c] |
| A.cpp:152:13:152:13 | b [b] | A.cpp:152:13:152:13 | b |
| A.cpp:154:13:154:13 | c [c] | A.cpp:154:13:154:13 | c |
| C.cpp:18:12:18:18 | C output argument [s1] | C.cpp:27:8:27:11 | *#this [s1] |
| C.cpp:18:12:18:18 | C output argument [s3] | C.cpp:27:8:27:11 | *#this [s3] |
| C.cpp:22:12:22:21 | Chi [s1] | C.cpp:24:5:24:25 | Chi [s1] |
| C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | Chi [s1] |
| C.cpp:22:9:22:22 | s1 [post update] [s1] | C.cpp:24:5:24:25 | Chi [s1] |
| C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | s1 [post update] [s1] |
| C.cpp:24:5:24:25 | Chi [s1] | C.cpp:18:12:18:18 | C output argument [s1] |
| C.cpp:24:5:24:25 | Chi [s3] | C.cpp:18:12:18:18 | C output argument [s3] |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | Chi [s3] |
| C.cpp:27:8:27:11 | *#this [s1] | C.cpp:29:10:29:11 | s1 |
| C.cpp:27:8:27:11 | *#this [s3] | C.cpp:31:10:31:11 | s3 |
| C.cpp:24:11:24:12 | s3 [post update] [s3] | C.cpp:24:5:24:25 | Chi [s3] |
| C.cpp:24:16:24:25 | new | C.cpp:24:11:24:12 | s3 [post update] [s3] |
| C.cpp:27:8:27:11 | *#this [s1] | C.cpp:29:10:29:11 | s1 [s1] |
| C.cpp:27:8:27:11 | *#this [s3] | C.cpp:31:10:31:11 | s3 [s3] |
| C.cpp:29:10:29:11 | s1 [s1] | C.cpp:29:10:29:11 | s1 |
| C.cpp:31:10:31:11 | s3 [s3] | C.cpp:31:10:31:11 | s3 |
| aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:9:6:9:7 | m1 [post update] [m1] | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:9:6:9:7 | m1 [post update] [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:6:9:7 | m1 [post update] [m1] |
| aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:25:17:25:19 | Chi [m1] | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:25:17:25:19 | Chi [m1] |
| aliasing.cpp:26:19:26:20 | Chi [m1] | aliasing.cpp:30:11:30:12 | m1 |
| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:26:19:26:20 | Chi [m1] |
| aliasing.cpp:13:5:13:6 | m1 [post update] [m1] | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:13:5:13:6 | m1 [post update] [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:5:13:6 | m1 [post update] [m1] |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:29:11:29:12 | m1 [m1] |
| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:30:11:30:12 | m1 [m1] |
| aliasing.cpp:29:11:29:12 | m1 [m1] | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:30:11:30:12 | m1 [m1] | aliasing.cpp:30:11:30:12 | m1 |
| aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 |
| aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Chi [m1] |
| aliasing.cpp:61:13:61:14 | Store [m1] | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:60:6:60:7 | m1 [post update] [m1] | aliasing.cpp:62:14:62:15 | m1 [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:6:60:7 | m1 [post update] [m1] |
| aliasing.cpp:62:14:62:15 | m1 [m1] | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 |
| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 |
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 |
| aliasing.cpp:98:3:98:21 | Chi [m1] | aliasing.cpp:100:14:100:14 | Store [m1] |
| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:3:98:21 | Chi [m1] |
| aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | aliasing.cpp:100:14:100:14 | Store [m1] |
| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:5:98:6 | m1 [post update] [m1] |
| aliasing.cpp:100:14:100:14 | Store [m1] | aliasing.cpp:102:8:102:10 | * ... |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:126:15:126:20 | taint_a_ptr output argument [array content] |
@@ -58,7 +70,19 @@ edges
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:3:106:20 | Chi [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:225:15:225:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:106:3:106:20 | Chi [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:126:15:126:20 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:131:15:131:16 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:136:15:136:17 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:158:15:158:20 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:164:15:164:20 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:225:15:225:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] |
| aliasing.cpp:121:15:121:16 | Chi [array content] | aliasing.cpp:122:8:122:12 | access to array |
| aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | aliasing.cpp:121:15:121:16 | Chi [array content] |
| aliasing.cpp:126:15:126:20 | Chi [array content] | aliasing.cpp:127:8:127:16 | * ... |
@@ -71,16 +95,37 @@ edges
| aliasing.cpp:158:15:158:20 | taint_a_ptr output argument [array content] | aliasing.cpp:158:15:158:20 | Chi [array content] |
| aliasing.cpp:164:15:164:20 | Chi [array content] | aliasing.cpp:165:8:165:16 | access to array |
| aliasing.cpp:164:15:164:20 | taint_a_ptr output argument [array content] | aliasing.cpp:164:15:164:20 | Chi [array content] |
| aliasing.cpp:175:15:175:22 | Chi | aliasing.cpp:175:15:175:22 | Chi [m1] |
| aliasing.cpp:175:15:175:22 | Chi [m1] | aliasing.cpp:176:13:176:14 | m1 |
| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] | aliasing.cpp:175:15:175:22 | Chi |
| aliasing.cpp:187:15:187:22 | Chi | aliasing.cpp:187:15:187:22 | Chi [m1] |
| aliasing.cpp:187:15:187:22 | Chi [m1] | aliasing.cpp:188:13:188:14 | Store [m1] |
| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] | aliasing.cpp:187:15:187:22 | Chi |
| aliasing.cpp:188:13:188:14 | Store [m1] | aliasing.cpp:189:15:189:16 | m1 |
| aliasing.cpp:200:15:200:24 | Chi | aliasing.cpp:200:15:200:24 | Chi [m1] |
| aliasing.cpp:200:15:200:24 | Chi [m1] | aliasing.cpp:201:15:201:16 | m1 |
| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] | aliasing.cpp:200:15:200:24 | Chi |
| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument | aliasing.cpp:175:21:175:22 | m1 [post update] [m1] |
| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument |
| aliasing.cpp:175:19:175:19 | s [post update] [s, m1] | aliasing.cpp:176:11:176:11 | s [s, m1] |
| aliasing.cpp:175:21:175:22 | m1 [post update] [m1] | aliasing.cpp:175:19:175:19 | s [post update] [s, m1] |
| aliasing.cpp:176:11:176:11 | s [s, m1] | aliasing.cpp:176:13:176:14 | m1 [m1] |
| aliasing.cpp:176:13:176:14 | m1 [m1] | aliasing.cpp:176:13:176:14 | m1 |
| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument | aliasing.cpp:187:21:187:22 | m1 [post update] [m1] |
| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument |
| aliasing.cpp:187:19:187:19 | s [post update] [s, m1] | aliasing.cpp:189:13:189:13 | s [s, m1] |
| aliasing.cpp:187:21:187:22 | m1 [post update] [m1] | aliasing.cpp:187:19:187:19 | s [post update] [s, m1] |
| aliasing.cpp:189:13:189:13 | s [s, m1] | aliasing.cpp:189:15:189:16 | m1 [m1] |
| aliasing.cpp:189:15:189:16 | m1 [m1] | aliasing.cpp:189:15:189:16 | m1 |
| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument | aliasing.cpp:200:23:200:24 | m1 [post update] [m1] |
| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument |
| aliasing.cpp:200:21:200:21 | s [post update] [s, m1] | aliasing.cpp:201:13:201:13 | s [s, m1] |
| aliasing.cpp:200:23:200:24 | m1 [post update] [m1] | aliasing.cpp:200:21:200:21 | s [post update] [s, m1] |
| aliasing.cpp:201:13:201:13 | s [s, m1] | aliasing.cpp:201:15:201:16 | m1 [m1] |
| aliasing.cpp:201:15:201:16 | m1 [m1] | aliasing.cpp:201:15:201:16 | m1 |
| aliasing.cpp:211:6:211:6 | s [post update] [s, m1] | aliasing.cpp:212:12:212:12 | s [s, m1] |
| aliasing.cpp:211:8:211:9 | m1 [post update] [m1] | aliasing.cpp:211:6:211:6 | s [post update] [s, m1] |
| aliasing.cpp:211:13:211:22 | call to user_input | aliasing.cpp:211:8:211:9 | m1 [post update] [m1] |
| aliasing.cpp:212:12:212:12 | s [m1] | aliasing.cpp:213:10:213:11 | m1 [m1] |
| aliasing.cpp:212:12:212:12 | s [s, m1] | aliasing.cpp:212:12:212:12 | s [m1] |
| aliasing.cpp:213:10:213:11 | m1 [m1] | aliasing.cpp:213:10:213:11 | m1 |
| aliasing.cpp:225:15:225:22 | taint_a_ptr output argument | aliasing.cpp:225:21:225:22 | m1 [post update] [m1] |
| aliasing.cpp:225:15:225:22 | taint_a_ptr output argument [array content] | aliasing.cpp:225:15:225:22 | taint_a_ptr output argument |
| aliasing.cpp:225:19:225:19 | s [post update] [s, m1] | aliasing.cpp:226:12:226:12 | s [s, m1] |
| aliasing.cpp:225:21:225:22 | m1 [post update] [m1] | aliasing.cpp:225:19:225:19 | s [post update] [s, m1] |
| aliasing.cpp:226:12:226:12 | s [m1] | aliasing.cpp:227:10:227:11 | m1 [m1] |
| aliasing.cpp:226:12:226:12 | s [s, m1] | aliasing.cpp:226:12:226:12 | s [m1] |
| aliasing.cpp:227:10:227:11 | m1 [m1] | aliasing.cpp:227:10:227:11 | m1 |
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array |
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... |
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... |
@@ -96,65 +141,126 @@ edges
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:84:10:84:10 | a [post update] [a] | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:84:10:84:10 | a [post update] [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:10:84:10 | a [post update] [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:10:84:10 | a [post update] [a] |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:88:9:88:9 | a [post update] [a] | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:88:9:88:9 | a [post update] [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:9:88:9 | a [post update] [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:9:88:9 | a [post update] [a] |
| by_reference.cpp:92:3:92:20 | Chi [array content] | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] |
| by_reference.cpp:92:3:92:20 | Chi [array content] | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] |
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:3:92:20 | Chi [array content] |
| by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] | by_reference.cpp:92:3:92:20 | Chi [array content] |
| by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] |
| by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] |
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] |
| by_reference.cpp:96:3:96:19 | Chi [array content] | by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] |
| by_reference.cpp:96:3:96:19 | Chi [array content] | by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] |
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:96:3:96:19 | Chi [array content] |
| by_reference.cpp:102:21:102:39 | Chi [a] | by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:21:102:39 | Chi [a] |
| by_reference.cpp:104:15:104:22 | Chi | by_reference.cpp:104:15:104:22 | Chi [a] |
| by_reference.cpp:104:15:104:22 | Chi [a] | by_reference.cpp:112:14:112:14 | a |
| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] | by_reference.cpp:104:15:104:22 | Chi |
| by_reference.cpp:106:21:106:41 | Chi [a] | by_reference.cpp:114:29:114:29 | a |
| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | by_reference.cpp:106:21:106:41 | Chi [a] |
| by_reference.cpp:108:15:108:24 | Chi | by_reference.cpp:108:15:108:24 | Chi [a] |
| by_reference.cpp:108:15:108:24 | Chi [a] | by_reference.cpp:116:16:116:16 | a |
| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] | by_reference.cpp:108:15:108:24 | Chi |
| by_reference.cpp:122:21:122:38 | Chi [a] | by_reference.cpp:130:27:130:27 | a |
| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:122:21:122:38 | Chi [a] |
| by_reference.cpp:124:15:124:21 | Chi | by_reference.cpp:124:15:124:21 | Chi [a] |
| by_reference.cpp:124:15:124:21 | Chi [a] | by_reference.cpp:132:14:132:14 | a |
| by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] | by_reference.cpp:124:15:124:21 | Chi |
| by_reference.cpp:126:21:126:40 | Chi [a] | by_reference.cpp:134:29:134:29 | a |
| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | by_reference.cpp:126:21:126:40 | Chi [a] |
| by_reference.cpp:128:15:128:23 | Chi | by_reference.cpp:128:15:128:23 | Chi [a] |
| by_reference.cpp:128:15:128:23 | Chi [a] | by_reference.cpp:136:16:136:16 | a |
| by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | by_reference.cpp:128:15:128:23 | Chi |
| by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] | by_reference.cpp:96:3:96:19 | Chi [array content] |
| by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] | by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] |
| by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] | by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] |
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:28:102:39 | inner_nested [post update] [a, a] |
| by_reference.cpp:102:28:102:39 | inner_nested [post update] [a, a] | by_reference.cpp:110:14:110:25 | inner_nested [a, a] |
| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument | by_reference.cpp:104:22:104:22 | a [post update] [a] |
| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument |
| by_reference.cpp:104:22:104:22 | a [post update] [a] | by_reference.cpp:112:14:112:14 | a [a] |
| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | by_reference.cpp:106:30:106:41 | inner_nested [post update] [a, a] |
| by_reference.cpp:106:30:106:41 | inner_nested [post update] [a, a] | by_reference.cpp:114:16:114:27 | inner_nested [a, a] |
| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument | by_reference.cpp:108:24:108:24 | a [post update] [a] |
| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument |
| by_reference.cpp:108:24:108:24 | a [post update] [a] | by_reference.cpp:116:16:116:16 | a [a] |
| by_reference.cpp:110:14:110:25 | inner_nested [a, a] | by_reference.cpp:110:27:110:27 | a [a] |
| by_reference.cpp:110:27:110:27 | a [a] | by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:112:14:112:14 | a [a] | by_reference.cpp:112:14:112:14 | a |
| by_reference.cpp:114:16:114:27 | inner_nested [a, a] | by_reference.cpp:114:29:114:29 | a [a] |
| by_reference.cpp:114:29:114:29 | a [a] | by_reference.cpp:114:29:114:29 | a |
| by_reference.cpp:116:16:116:16 | a [a] | by_reference.cpp:116:16:116:16 | a |
| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:122:27:122:38 | inner_nested [post update] [a, a] |
| by_reference.cpp:122:27:122:38 | inner_nested [post update] [a, a] | by_reference.cpp:130:14:130:25 | inner_nested [a, a] |
| by_reference.cpp:124:15:124:21 | taint_a_ref output argument | by_reference.cpp:124:21:124:21 | a [post update] [a] |
| by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] | by_reference.cpp:124:15:124:21 | taint_a_ref output argument |
| by_reference.cpp:124:21:124:21 | a [post update] [a] | by_reference.cpp:132:14:132:14 | a [a] |
| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | by_reference.cpp:126:29:126:40 | inner_nested [post update] [a, a] |
| by_reference.cpp:126:29:126:40 | inner_nested [post update] [a, a] | by_reference.cpp:134:16:134:27 | inner_nested [a, a] |
| by_reference.cpp:128:15:128:23 | taint_a_ref output argument | by_reference.cpp:128:23:128:23 | a [post update] [a] |
| by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | by_reference.cpp:128:15:128:23 | taint_a_ref output argument |
| by_reference.cpp:128:23:128:23 | a [post update] [a] | by_reference.cpp:136:16:136:16 | a [a] |
| by_reference.cpp:130:14:130:25 | inner_nested [a, a] | by_reference.cpp:130:27:130:27 | a [a] |
| by_reference.cpp:130:27:130:27 | a [a] | by_reference.cpp:130:27:130:27 | a |
| by_reference.cpp:132:14:132:14 | a [a] | by_reference.cpp:132:14:132:14 | a |
| by_reference.cpp:134:16:134:27 | inner_nested [a, a] | by_reference.cpp:134:29:134:29 | a [a] |
| by_reference.cpp:134:29:134:29 | a [a] | by_reference.cpp:134:29:134:29 | a |
| by_reference.cpp:136:16:136:16 | a [a] | by_reference.cpp:136:16:136:16 | a |
| by_reference.cpp:140:3:140:27 | Chi [array content] | by_reference.cpp:145:15:145:16 | taint_a_ptr output argument [array content] |
| by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] | by_reference.cpp:140:3:140:27 | Chi [array content] |
| by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] | by_reference.cpp:145:15:145:16 | taint_a_ptr output argument [array content] |
| by_reference.cpp:140:9:140:27 | (char *)... | by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] |
| by_reference.cpp:140:9:140:27 | (const char *)... | by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] |
| by_reference.cpp:140:16:140:25 | call to user_input | by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] |
| by_reference.cpp:145:15:145:16 | taint_a_ptr output argument | by_reference.cpp:146:8:146:8 | s |
| by_reference.cpp:145:15:145:16 | taint_a_ptr output argument [array content] | by_reference.cpp:145:15:145:16 | taint_a_ptr output argument |
| complex.cpp:40:17:40:17 | *b [a_] | complex.cpp:42:18:42:18 | call to a |
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | Chi [b_] |
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | a output argument [b_] |
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:42:16:42:16 | Chi [b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:42:16:42:16 | Chi [b_] |
| complex.cpp:40:17:40:17 | *b [f, f, a_] | complex.cpp:42:10:42:14 | inner [f, f, a_] |
| complex.cpp:40:17:40:17 | *b [f, f, b_] | complex.cpp:42:10:42:14 | inner [f, f, b_] |
| complex.cpp:40:17:40:17 | *b [f, f, b_] | complex.cpp:42:16:42:16 | a output argument [f, f, b_] |
| complex.cpp:40:17:40:17 | *b [f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, b_] |
| complex.cpp:40:17:40:17 | *b [f, f, f, f, a_] | complex.cpp:42:10:42:14 | inner [f, f, f, f, a_] |
| complex.cpp:42:10:42:14 | inner [f, f, a_] | complex.cpp:42:16:42:16 | f [f, a_] |
| complex.cpp:42:10:42:14 | inner [f, f, b_] | complex.cpp:42:16:42:16 | f [f, b_] |
| complex.cpp:42:10:42:14 | inner [f, f, f, f, a_] | complex.cpp:42:16:42:16 | f [f, f, f, a_] |
| complex.cpp:42:10:42:14 | inner [post update] [f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, b_] |
| complex.cpp:42:10:42:14 | inner [post update] [f, f, f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, f, f, b_] |
| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:42:16:42:16 | f [post update] [f, b_] |
| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:53:12:53:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:42:16:42:16 | a output argument [f, f, b_] | complex.cpp:42:16:42:16 | f [post update] [f, f, f, b_] |
| complex.cpp:42:16:42:16 | a output argument [f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, b_] |
| complex.cpp:42:16:42:16 | f [f, a_] | complex.cpp:42:18:42:18 | call to a |
| complex.cpp:42:16:42:16 | f [f, b_] | complex.cpp:42:16:42:16 | a output argument [b_] |
| complex.cpp:42:16:42:16 | f [f, f, f, a_] | complex.cpp:42:10:42:14 | inner [f, f, a_] |
| complex.cpp:42:16:42:16 | f [post update] [f, b_] | complex.cpp:42:10:42:14 | inner [post update] [f, f, b_] |
| complex.cpp:42:16:42:16 | f [post update] [f, f, f, b_] | complex.cpp:42:10:42:14 | inner [post update] [f, f, f, f, b_] |
| complex.cpp:43:10:43:14 | inner [f, f, b_] | complex.cpp:43:16:43:16 | f [f, b_] |
| complex.cpp:43:10:43:14 | inner [f, f, f, f, b_] | complex.cpp:43:16:43:16 | f [f, f, f, b_] |
| complex.cpp:43:16:43:16 | f [f, b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:43:16:43:16 | f [f, f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, b_] |
| complex.cpp:53:6:53:10 | inner [post update] [f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, a_] |
| complex.cpp:53:12:53:12 | f [post update] [f, a_] | complex.cpp:53:6:53:10 | inner [post update] [f, f, a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:53:12:53:12 | Chi [a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:53:12:53:12 | f [post update] [f, a_] |
| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:12:53:12 | setA output argument [a_] |
| complex.cpp:54:12:54:12 | Chi [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:54:6:54:10 | inner [post update] [f, f, b_] | complex.cpp:40:17:40:17 | *b [f, f, b_] |
| complex.cpp:54:12:54:12 | f [post update] [f, b_] | complex.cpp:54:6:54:10 | inner [post update] [f, f, b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:54:12:54:12 | Chi [b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:54:12:54:12 | f [post update] [f, b_] |
| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:12:54:12 | setB output argument [b_] |
| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:56:12:56:12 | Chi [a_] |
| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] |
| complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, a_] |
| complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] | complex.cpp:56:6:56:10 | inner [f, f, a_] |
| complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] | complex.cpp:56:12:56:12 | setB output argument [f, f, a_] |
| complex.cpp:55:12:55:12 | f [post update] [f, a_] | complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:55:12:55:12 | Chi [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:56:12:56:12 | Chi [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:55:12:55:12 | f [post update] [f, a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] |
| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:12:55:12 | setA output argument [a_] |
| complex.cpp:56:12:56:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:56:12:56:12 | Chi [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:56:6:56:10 | inner [f, f, a_] | complex.cpp:56:12:56:12 | f [f, a_] |
| complex.cpp:56:6:56:10 | inner [post update] [f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, a_] |
| complex.cpp:56:6:56:10 | inner [post update] [f, f, b_] | complex.cpp:40:17:40:17 | *b [f, f, b_] |
| complex.cpp:56:6:56:10 | inner [post update] [f, f, f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, f, f, a_] |
| complex.cpp:56:12:56:12 | f [f, a_] | complex.cpp:56:12:56:12 | setB output argument [a_] |
| complex.cpp:56:12:56:12 | f [post update] [f, a_] | complex.cpp:56:6:56:10 | inner [post update] [f, f, a_] |
| complex.cpp:56:12:56:12 | f [post update] [f, b_] | complex.cpp:56:6:56:10 | inner [post update] [f, f, b_] |
| complex.cpp:56:12:56:12 | f [post update] [f, f, f, a_] | complex.cpp:56:6:56:10 | inner [post update] [f, f, f, f, a_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:56:12:56:12 | Chi [a_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:56:12:56:12 | f [post update] [f, a_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:56:12:56:12 | Chi [b_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:56:12:56:12 | f [post update] [f, b_] |
| complex.cpp:56:12:56:12 | setB output argument [f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, a_] |
| complex.cpp:56:12:56:12 | setB output argument [f, f, a_] | complex.cpp:56:12:56:12 | f [post update] [f, f, f, a_] |
| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:12:56:12 | setB output argument [b_] |
| constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:12:28:12 | call to a |
| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] |
@@ -182,21 +288,25 @@ edges
| simple.cpp:42:5:42:5 | setB output argument [a_] | simple.cpp:26:15:26:15 | *f [a_] |
| simple.cpp:42:5:42:5 | setB output argument [b_] | simple.cpp:26:15:26:15 | *f [b_] |
| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:5:42:5 | setB output argument [b_] |
| simple.cpp:65:5:65:22 | Store [i] | simple.cpp:66:12:66:12 | Store [i] |
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] |
| simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i |
| simple.cpp:83:9:83:28 | Chi [f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Chi [f1] |
| simple.cpp:92:5:92:22 | Store [i] | simple.cpp:93:20:93:20 | Store [i] |
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | Store [i] |
| simple.cpp:93:20:93:20 | Store [i] | simple.cpp:94:13:94:13 | i |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:20:20:29 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | Chi [a] |
| simple.cpp:65:7:65:7 | i [post update] [i] | simple.cpp:67:13:67:13 | i [i] |
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:7:65:7 | i [post update] [i] |
| simple.cpp:67:13:67:13 | i [i] | simple.cpp:67:13:67:13 | i |
| simple.cpp:83:9:83:10 | f2 [post update] [f1, f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| simple.cpp:83:12:83:13 | f1 [post update] [f1] | simple.cpp:83:9:83:10 | f2 [post update] [f1, f1] |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:12:83:13 | f1 [post update] [f1] |
| simple.cpp:92:7:92:7 | i [post update] [i] | simple.cpp:94:13:94:13 | i [i] |
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:7:92:7 | i [post update] [i] |
| simple.cpp:94:13:94:13 | i [i] | simple.cpp:94:13:94:13 | i |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a [a] |
| struct_init.c:15:12:15:12 | a [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:17:20:36 | a [post update] [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:17:20:36 | a [post update] [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a |
| struct_init.c:27:7:27:16 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | Chi [a] |
| struct_init.c:26:23:29:3 | nestedAB [post update] [nestedAB, a] | struct_init.c:36:17:36:24 | nestedAB [nestedAB, a] |
| struct_init.c:27:5:27:23 | a [post update] [a] | struct_init.c:26:23:29:3 | nestedAB [post update] [nestedAB, a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:5:27:23 | a [post update] [a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a |
| struct_init.c:36:17:36:24 | nestedAB [nestedAB, a] | struct_init.c:14:24:14:25 | *ab [a] |
nodes
| A.cpp:55:5:55:5 | set output argument [c] | semmle.label | set output argument [c] |
| A.cpp:55:12:55:19 | (C *)... | semmle.label | (C *)... |
@@ -206,66 +316,75 @@ nodes
| A.cpp:57:17:57:23 | new | semmle.label | new |
| A.cpp:57:28:57:30 | call to get | semmle.label | call to get |
| A.cpp:98:12:98:18 | new | semmle.label | new |
| A.cpp:100:5:100:13 | Chi [a] | semmle.label | Chi [a] |
| A.cpp:100:9:100:9 | a [post update] [a] | semmle.label | a [post update] [a] |
| A.cpp:103:14:103:14 | *c [a] | semmle.label | *c [a] |
| A.cpp:107:16:107:16 | a | semmle.label | a |
| A.cpp:107:16:107:16 | a [a] | semmle.label | a [a] |
| A.cpp:126:5:126:5 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:126:5:126:5 | set output argument [c] | semmle.label | set output argument [c] |
| A.cpp:126:12:126:18 | new | semmle.label | new |
| A.cpp:131:8:131:8 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] |
| A.cpp:132:13:132:13 | c | semmle.label | c |
| A.cpp:132:13:132:13 | c [c] | semmle.label | c [c] |
| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:142:10:142:10 | c [post update] [c] | semmle.label | c [post update] [c] |
| A.cpp:142:14:142:20 | new | semmle.label | new |
| A.cpp:143:7:143:31 | Chi [b] | semmle.label | Chi [b] |
| A.cpp:143:13:143:13 | b [post update] [b] | semmle.label | b [post update] [b] |
| A.cpp:143:25:143:31 | new | semmle.label | new |
| A.cpp:150:12:150:18 | new | semmle.label | new |
| A.cpp:151:12:151:24 | Chi [b] | semmle.label | Chi [b] |
| A.cpp:151:12:151:24 | D output argument [b] | semmle.label | D output argument [b] |
| A.cpp:151:18:151:18 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] |
| A.cpp:152:13:152:13 | b | semmle.label | b |
| A.cpp:152:13:152:13 | b [b] | semmle.label | b [b] |
| A.cpp:154:13:154:13 | c | semmle.label | c |
| A.cpp:154:13:154:13 | c [c] | semmle.label | c [c] |
| C.cpp:18:12:18:18 | C output argument [s1] | semmle.label | C output argument [s1] |
| C.cpp:18:12:18:18 | C output argument [s3] | semmle.label | C output argument [s3] |
| C.cpp:22:12:22:21 | Chi [s1] | semmle.label | Chi [s1] |
| C.cpp:22:9:22:22 | s1 [post update] [s1] | semmle.label | s1 [post update] [s1] |
| C.cpp:22:12:22:21 | new | semmle.label | new |
| C.cpp:24:5:24:25 | Chi [s1] | semmle.label | Chi [s1] |
| C.cpp:24:5:24:25 | Chi [s3] | semmle.label | Chi [s3] |
| C.cpp:24:11:24:12 | s3 [post update] [s3] | semmle.label | s3 [post update] [s3] |
| C.cpp:24:16:24:25 | new | semmle.label | new |
| 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 | s1 [s1] | semmle.label | s1 [s1] |
| C.cpp:31:10:31:11 | s3 | semmle.label | s3 |
| C.cpp:31:10:31:11 | s3 [s3] | semmle.label | s3 [s3] |
| aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:9:6:9:7 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:13:3:13:21 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:13:5:13:6 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:25:17:25:19 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] |
| aliasing.cpp:26:19:26:20 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | semmle.label | referenceSetter output argument [m1] |
| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 |
| aliasing.cpp:29:11:29:12 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 |
| aliasing.cpp:30:11:30:12 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:37:13:37:22 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 |
| aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:60:6:60:7 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:61:13:61:14 | Store [m1] | semmle.label | Store [m1] |
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
| aliasing.cpp:62:14:62:15 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:79:11:79:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 |
| aliasing.cpp:86:10:86:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 |
| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
| aliasing.cpp:98:3:98:21 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] |
| aliasing.cpp:98:10:98:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:100:14:100:14 | Store [m1] | semmle.label | Store [m1] |
| aliasing.cpp:102:8:102:10 | * ... | semmle.label | * ... |
| aliasing.cpp:106:3:106:20 | Chi [array content] | semmle.label | Chi [array content] |
| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] |
| aliasing.cpp:106:9:106:18 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:121:15:121:16 | Chi [array content] | semmle.label | Chi [array content] |
| aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
@@ -285,19 +404,42 @@ nodes
| aliasing.cpp:164:15:164:20 | Chi [array content] | semmle.label | Chi [array content] |
| aliasing.cpp:164:15:164:20 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
| aliasing.cpp:165:8:165:16 | access to array | semmle.label | access to array |
| aliasing.cpp:175:15:175:22 | Chi | semmle.label | Chi |
| aliasing.cpp:175:15:175:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument |
| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
| aliasing.cpp:175:19:175:19 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] |
| aliasing.cpp:175:21:175:22 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] |
| aliasing.cpp:176:11:176:11 | s [s, m1] | semmle.label | s [s, m1] |
| aliasing.cpp:176:13:176:14 | m1 | semmle.label | m1 |
| aliasing.cpp:187:15:187:22 | Chi | semmle.label | Chi |
| aliasing.cpp:187:15:187:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:176:13:176:14 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument |
| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
| aliasing.cpp:188:13:188:14 | Store [m1] | semmle.label | Store [m1] |
| aliasing.cpp:187:19:187:19 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] |
| aliasing.cpp:187:21:187:22 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] |
| aliasing.cpp:189:13:189:13 | s [s, m1] | semmle.label | s [s, m1] |
| aliasing.cpp:189:15:189:16 | m1 | semmle.label | m1 |
| aliasing.cpp:200:15:200:24 | Chi | semmle.label | Chi |
| aliasing.cpp:200:15:200:24 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:189:15:189:16 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument |
| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
| aliasing.cpp:200:21:200:21 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] |
| aliasing.cpp:200:23:200:24 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] |
| aliasing.cpp:201:13:201:13 | s [s, m1] | semmle.label | s [s, m1] |
| aliasing.cpp:201:15:201:16 | m1 | semmle.label | m1 |
| aliasing.cpp:201:15:201:16 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:211:6:211:6 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] |
| aliasing.cpp:211:8:211:9 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] |
| aliasing.cpp:211:13:211:22 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:212:12:212:12 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:212:12:212:12 | s [s, m1] | semmle.label | s [s, m1] |
| aliasing.cpp:213:10:213:11 | m1 | semmle.label | m1 |
| aliasing.cpp:213:10:213:11 | m1 [m1] | semmle.label | m1 [m1] |
| aliasing.cpp:225:15:225:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument |
| aliasing.cpp:225:15:225:22 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
| aliasing.cpp:225:19:225:19 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] |
| aliasing.cpp:225:21:225:22 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] |
| aliasing.cpp:226:12:226:12 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:226:12:226:12 | s [s, m1] | semmle.label | s [s, m1] |
| aliasing.cpp:227:10:227:11 | m1 | semmle.label | m1 |
| aliasing.cpp:227:10:227:11 | m1 [m1] | semmle.label | m1 [m1] |
| arrays.cpp:6:12:6:21 | call to user_input | semmle.label | call to user_input |
| arrays.cpp:7:8:7:13 | access to array | semmle.label | access to array |
| arrays.cpp:9:8:9:11 | * ... | semmle.label | * ... |
@@ -319,60 +461,111 @@ nodes
| by_reference.cpp:68:21:68:30 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | semmle.label | call to nonMemberGetA |
| by_reference.cpp:84:3:84:25 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:84:10:84:10 | a [post update] [a] | semmle.label | a [post update] [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:88:3:88:24 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:88:9:88:9 | a [post update] [a] | semmle.label | a [post update] [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:92:3:92:20 | Chi [array content] | semmle.label | Chi [array content] |
| by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] |
| by_reference.cpp:92:9:92:18 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:96:3:96:19 | Chi [array content] | semmle.label | Chi [array content] |
| by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] |
| by_reference.cpp:96:8:96:17 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:102:21:102:39 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:104:15:104:22 | Chi | semmle.label | Chi |
| by_reference.cpp:104:15:104:22 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:102:28:102:39 | inner_nested [post update] [a, a] | semmle.label | inner_nested [post update] [a, a] |
| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument |
| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
| by_reference.cpp:106:21:106:41 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:104:22:104:22 | a [post update] [a] | semmle.label | a [post update] [a] |
| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:108:15:108:24 | Chi | semmle.label | Chi |
| by_reference.cpp:108:15:108:24 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:106:30:106:41 | inner_nested [post update] [a, a] | semmle.label | inner_nested [post update] [a, a] |
| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument |
| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
| by_reference.cpp:108:24:108:24 | a [post update] [a] | semmle.label | a [post update] [a] |
| by_reference.cpp:110:14:110:25 | inner_nested [a, a] | semmle.label | inner_nested [a, a] |
| by_reference.cpp:110:27:110:27 | a | semmle.label | a |
| by_reference.cpp:110:27:110:27 | a [a] | semmle.label | a [a] |
| by_reference.cpp:112:14:112:14 | a | semmle.label | a |
| by_reference.cpp:112:14:112:14 | a [a] | semmle.label | a [a] |
| by_reference.cpp:114:16:114:27 | inner_nested [a, a] | semmle.label | inner_nested [a, a] |
| by_reference.cpp:114:29:114:29 | a | semmle.label | a |
| by_reference.cpp:114:29:114:29 | a [a] | semmle.label | a [a] |
| by_reference.cpp:116:16:116:16 | a | semmle.label | a |
| by_reference.cpp:122:21:122:38 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:116:16:116:16 | a [a] | semmle.label | a [a] |
| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] |
| by_reference.cpp:124:15:124:21 | Chi | semmle.label | Chi |
| by_reference.cpp:124:15:124:21 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:122:27:122:38 | inner_nested [post update] [a, a] | semmle.label | inner_nested [post update] [a, a] |
| by_reference.cpp:124:15:124:21 | taint_a_ref output argument | semmle.label | taint_a_ref output argument |
| by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] | semmle.label | taint_a_ref output argument [array content] |
| by_reference.cpp:126:21:126:40 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:124:21:124:21 | a [post update] [a] | semmle.label | a [post update] [a] |
| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] |
| by_reference.cpp:128:15:128:23 | Chi | semmle.label | Chi |
| by_reference.cpp:128:15:128:23 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:126:29:126:40 | inner_nested [post update] [a, a] | semmle.label | inner_nested [post update] [a, a] |
| by_reference.cpp:128:15:128:23 | taint_a_ref output argument | semmle.label | taint_a_ref output argument |
| by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | semmle.label | taint_a_ref output argument [array content] |
| by_reference.cpp:128:23:128:23 | a [post update] [a] | semmle.label | a [post update] [a] |
| by_reference.cpp:130:14:130:25 | inner_nested [a, a] | semmle.label | inner_nested [a, a] |
| by_reference.cpp:130:27:130:27 | a | semmle.label | a |
| by_reference.cpp:130:27:130:27 | a [a] | semmle.label | a [a] |
| by_reference.cpp:132:14:132:14 | a | semmle.label | a |
| by_reference.cpp:132:14:132:14 | a [a] | semmle.label | a [a] |
| by_reference.cpp:134:16:134:27 | inner_nested [a, a] | semmle.label | inner_nested [a, a] |
| by_reference.cpp:134:29:134:29 | a | semmle.label | a |
| by_reference.cpp:134:29:134:29 | a [a] | semmle.label | a [a] |
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
| by_reference.cpp:136:16:136:16 | a [a] | semmle.label | a [a] |
| by_reference.cpp:140:3:140:27 | Chi [array content] | semmle.label | Chi [array content] |
| by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] |
| by_reference.cpp:140:9:140:27 | (char *)... | semmle.label | (char *)... |
| by_reference.cpp:140:9:140:27 | (const char *)... | semmle.label | (const char *)... |
| by_reference.cpp:140:16:140:25 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:145:15:145:16 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument |
| by_reference.cpp:145:15:145:16 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
| by_reference.cpp:146:8:146:8 | s | semmle.label | s |
| complex.cpp:40:17:40:17 | *b [a_] | semmle.label | *b [a_] |
| complex.cpp:40:17:40:17 | *b [b_] | semmle.label | *b [b_] |
| complex.cpp:42:16:42:16 | Chi [b_] | semmle.label | Chi [b_] |
| complex.cpp:40:17:40:17 | *b [f, f, a_] | semmle.label | *b [f, f, a_] |
| complex.cpp:40:17:40:17 | *b [f, f, b_] | semmle.label | *b [f, f, b_] |
| complex.cpp:40:17:40:17 | *b [f, f, f, f, a_] | semmle.label | *b [f, f, f, f, a_] |
| complex.cpp:42:10:42:14 | inner [f, f, a_] | semmle.label | inner [f, f, a_] |
| complex.cpp:42:10:42:14 | inner [f, f, b_] | semmle.label | inner [f, f, b_] |
| complex.cpp:42:10:42:14 | inner [f, f, f, f, a_] | semmle.label | inner [f, f, f, f, a_] |
| complex.cpp:42:10:42:14 | inner [post update] [f, f, b_] | semmle.label | inner [post update] [f, f, b_] |
| complex.cpp:42:10:42:14 | inner [post update] [f, f, f, f, b_] | semmle.label | inner [post update] [f, f, f, f, b_] |
| complex.cpp:42:16:42:16 | a output argument [b_] | semmle.label | a output argument [b_] |
| complex.cpp:42:16:42:16 | a output argument [f, f, b_] | semmle.label | a output argument [f, f, b_] |
| complex.cpp:42:16:42:16 | f [f, a_] | semmle.label | f [f, a_] |
| complex.cpp:42:16:42:16 | f [f, b_] | semmle.label | f [f, b_] |
| complex.cpp:42:16:42:16 | f [f, f, f, a_] | semmle.label | f [f, f, f, a_] |
| complex.cpp:42:16:42:16 | f [post update] [f, b_] | semmle.label | f [post update] [f, b_] |
| complex.cpp:42:16:42:16 | f [post update] [f, f, f, b_] | semmle.label | f [post update] [f, f, f, b_] |
| complex.cpp:42:18:42:18 | call to a | semmle.label | call to a |
| complex.cpp:43:10:43:14 | inner [f, f, b_] | semmle.label | inner [f, f, b_] |
| complex.cpp:43:10:43:14 | inner [f, f, f, f, b_] | semmle.label | inner [f, f, f, f, b_] |
| complex.cpp:43:16:43:16 | f [f, b_] | semmle.label | f [f, b_] |
| complex.cpp:43:16:43:16 | f [f, f, f, b_] | semmle.label | f [f, f, f, b_] |
| complex.cpp:43:18:43:18 | call to b | semmle.label | call to b |
| complex.cpp:53:12:53:12 | Chi [a_] | semmle.label | Chi [a_] |
| complex.cpp:53:6:53:10 | inner [post update] [f, f, a_] | semmle.label | inner [post update] [f, f, a_] |
| complex.cpp:53:12:53:12 | f [post update] [f, a_] | semmle.label | f [post update] [f, a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | semmle.label | setA output argument [a_] |
| complex.cpp:53:19:53:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:54:12:54:12 | Chi [b_] | semmle.label | Chi [b_] |
| complex.cpp:54:6:54:10 | inner [post update] [f, f, b_] | semmle.label | inner [post update] [f, f, b_] |
| complex.cpp:54:12:54:12 | f [post update] [f, b_] | semmle.label | f [post update] [f, b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | semmle.label | setB output argument [b_] |
| complex.cpp:54:19:54:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:55:12:55:12 | Chi [a_] | semmle.label | Chi [a_] |
| complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] | semmle.label | inner [post update] [f, f, a_] |
| complex.cpp:55:12:55:12 | f [post update] [f, a_] | semmle.label | f [post update] [f, a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | semmle.label | setA output argument [a_] |
| complex.cpp:55:19:55:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:56:12:56:12 | Chi [a_] | semmle.label | Chi [a_] |
| complex.cpp:56:12:56:12 | Chi [b_] | semmle.label | Chi [b_] |
| complex.cpp:56:6:56:10 | inner [f, f, a_] | semmle.label | inner [f, f, a_] |
| complex.cpp:56:6:56:10 | inner [post update] [f, f, a_] | semmle.label | inner [post update] [f, f, a_] |
| complex.cpp:56:6:56:10 | inner [post update] [f, f, b_] | semmle.label | inner [post update] [f, f, b_] |
| complex.cpp:56:6:56:10 | inner [post update] [f, f, f, f, a_] | semmle.label | inner [post update] [f, f, f, f, a_] |
| complex.cpp:56:12:56:12 | f [f, a_] | semmle.label | f [f, a_] |
| complex.cpp:56:12:56:12 | f [post update] [f, a_] | semmle.label | f [post update] [f, a_] |
| complex.cpp:56:12:56:12 | f [post update] [f, b_] | semmle.label | f [post update] [f, b_] |
| complex.cpp:56:12:56:12 | f [post update] [f, f, f, a_] | semmle.label | f [post update] [f, f, f, a_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | semmle.label | setB output argument [a_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | semmle.label | setB output argument [b_] |
| complex.cpp:56:12:56:12 | setB output argument [f, f, a_] | semmle.label | setB output argument [f, f, a_] |
| complex.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input |
| constructors.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] |
| constructors.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] |
@@ -401,25 +594,29 @@ nodes
| simple.cpp:42:5:42:5 | setB output argument [a_] | semmle.label | setB output argument [a_] |
| simple.cpp:42:5:42:5 | setB output argument [b_] | semmle.label | setB output argument [b_] |
| simple.cpp:42:12:42:21 | call to user_input | semmle.label | call to user_input |
| simple.cpp:65:5:65:22 | Store [i] | semmle.label | Store [i] |
| simple.cpp:65:7:65:7 | i [post update] [i] | semmle.label | i [post update] [i] |
| simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] |
| simple.cpp:67:13:67:13 | i | semmle.label | i |
| simple.cpp:83:9:83:28 | Chi [f1] | semmle.label | Chi [f1] |
| simple.cpp:67:13:67:13 | i [i] | semmle.label | i [i] |
| simple.cpp:83:9:83:10 | f2 [post update] [f1, f1] | semmle.label | f2 [post update] [f1, f1] |
| simple.cpp:83:12:83:13 | f1 [post update] [f1] | semmle.label | f1 [post update] [f1] |
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
| simple.cpp:92:5:92:22 | Store [i] | semmle.label | Store [i] |
| simple.cpp:92:7:92:7 | i [post update] [i] | semmle.label | i [post update] [i] |
| simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:93:20:93:20 | Store [i] | semmle.label | Store [i] |
| simple.cpp:94:13:94:13 | i | semmle.label | i |
| simple.cpp:94:13:94:13 | i [i] | semmle.label | i [i] |
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
| struct_init.c:20:20:20:29 | Chi [a] | semmle.label | Chi [a] |
| struct_init.c:15:12:15:12 | a [a] | semmle.label | a [a] |
| struct_init.c:20:17:20:36 | a [post update] [a] | semmle.label | a [post update] [a] |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:22:11:22:11 | a | semmle.label | a |
| struct_init.c:27:7:27:16 | Chi [a] | semmle.label | Chi [a] |
| struct_init.c:26:23:29:3 | nestedAB [post update] [nestedAB, a] | semmle.label | nestedAB [post update] [nestedAB, a] |
| struct_init.c:27:5:27:23 | a [post update] [a] | semmle.label | a [post update] [a] |
| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input |
| struct_init.c:31:23:31:23 | a | semmle.label | a |
| struct_init.c:36:17:36:24 | nestedAB [nestedAB, a] | semmle.label | nestedAB [nestedAB, a] |
#select
| A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | (C *)... | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | (C *)... | (C *)... |
| A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new |
@@ -449,6 +646,8 @@ nodes
| aliasing.cpp:176:13:176:14 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:176:13:176:14 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input |
| aliasing.cpp:189:15:189:16 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:189:15:189:16 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input |
| aliasing.cpp:201:15:201:16 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:201:15:201:16 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input |
| aliasing.cpp:213:10:213:11 | m1 | aliasing.cpp:211:13:211:22 | call to user_input | aliasing.cpp:213:10:213:11 | m1 | m1 flows from $@ | aliasing.cpp:211:13:211:22 | call to user_input | call to user_input |
| aliasing.cpp:227:10:227:11 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:227:10:227:11 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input |
| arrays.cpp:7:8:7:13 | access to array | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array | access to array flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
| arrays.cpp:9:8:9:11 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
| arrays.cpp:10:8:10:15 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
@@ -466,6 +665,9 @@ nodes
| by_reference.cpp:132:14:132:14 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:132:14:132:14 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input |
| by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:136:16:136:16 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:136:16:136:16 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input |
| by_reference.cpp:146:8:146:8 | s | by_reference.cpp:140:9:140:27 | (char *)... | by_reference.cpp:146:8:146:8 | s | s flows from $@ | by_reference.cpp:140:9:140:27 | (char *)... | (char *)... |
| by_reference.cpp:146:8:146:8 | s | by_reference.cpp:140:9:140:27 | (const char *)... | by_reference.cpp:146:8:146:8 | s | s flows from $@ | by_reference.cpp:140:9:140:27 | (const char *)... | (const char *)... |
| by_reference.cpp:146:8:146:8 | s | by_reference.cpp:140:16:140:25 | call to user_input | by_reference.cpp:146:8:146:8 | s | s flows from $@ | by_reference.cpp:140:16:140:25 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:53:19:53:28 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:55:19:55:28 | call to user_input | call to user_input |
| complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input |

View File

@@ -1,12 +1,12 @@
| A.cpp:25:13:25:13 | c | AST only |
| A.cpp:27:28:27:28 | c | AST only |
| A.cpp:28:29:28:29 | this | IR only |
| A.cpp:31:20:31:20 | c | AST only |
| A.cpp:40:5:40:6 | cc | AST only |
| A.cpp:41:5:41:6 | ct | AST only |
| A.cpp:42:10:42:12 | & ... | AST only |
| A.cpp:43:10:43:12 | & ... | AST only |
| A.cpp:48:20:48:20 | c | AST only |
| A.cpp:49:10:49:10 | b | AST only |
| A.cpp:49:13:49:13 | c | AST only |
| A.cpp:55:5:55:5 | b | AST only |
| A.cpp:56:10:56:10 | b | AST only |
@@ -14,15 +14,11 @@
| A.cpp:57:28:57:30 | call to get | AST only |
| A.cpp:64:10:64:15 | this | AST only |
| A.cpp:64:17:64:18 | b1 | AST only |
| A.cpp:65:10:65:11 | b1 | AST only |
| A.cpp:65:14:65:14 | c | AST only |
| A.cpp:66:10:66:11 | b2 | AST only |
| A.cpp:66:14:66:14 | c | AST only |
| A.cpp:73:10:73:19 | this | AST only |
| A.cpp:73:21:73:22 | b1 | AST only |
| A.cpp:74:10:74:11 | b1 | AST only |
| A.cpp:74:14:74:14 | c | AST only |
| A.cpp:75:10:75:11 | b2 | AST only |
| A.cpp:75:14:75:14 | c | AST only |
| A.cpp:81:10:81:15 | this | AST only |
| A.cpp:81:17:81:18 | b1 | AST only |
@@ -34,85 +30,61 @@
| A.cpp:100:9:100:9 | a | AST only |
| A.cpp:101:5:101:6 | this | AST only |
| A.cpp:101:8:101:9 | c1 | AST only |
| A.cpp:107:12:107:13 | c1 | AST only |
| A.cpp:107:16:107:16 | a | AST only |
| A.cpp:120:12:120:13 | c1 | AST only |
| A.cpp:120:16:120:16 | a | AST only |
| A.cpp:126:5:126:5 | b | AST only |
| A.cpp:131:5:131:6 | this | AST only |
| A.cpp:131:8:131:8 | b | AST only |
| A.cpp:132:10:132:10 | b | AST only |
| A.cpp:132:13:132:13 | c | AST only |
| A.cpp:142:10:142:10 | c | AST only |
| A.cpp:143:13:143:13 | b | AST only |
| A.cpp:151:18:151:18 | b | AST only |
| A.cpp:151:21:151:21 | this | AST only |
| A.cpp:152:10:152:10 | d | AST only |
| A.cpp:152:13:152:13 | b | AST only |
| A.cpp:153:10:153:10 | d | AST only |
| A.cpp:153:13:153:13 | b | AST only |
| A.cpp:153:16:153:16 | c | AST only |
| A.cpp:154:10:154:10 | b | AST only |
| A.cpp:154:13:154:13 | c | AST only |
| A.cpp:160:29:160:29 | b | AST only |
| A.cpp:161:38:161:39 | l1 | AST only |
| A.cpp:162:38:162:39 | l2 | AST only |
| A.cpp:163:10:163:11 | l3 | AST only |
| A.cpp:163:14:163:17 | head | AST only |
| A.cpp:164:10:164:11 | l3 | AST only |
| A.cpp:164:14:164:17 | next | AST only |
| A.cpp:164:20:164:23 | head | AST only |
| A.cpp:165:10:165:11 | l3 | AST only |
| A.cpp:165:14:165:17 | next | AST only |
| A.cpp:165:20:165:23 | next | AST only |
| A.cpp:165:26:165:29 | head | AST only |
| A.cpp:166:10:166:11 | l3 | AST only |
| A.cpp:166:14:166:17 | next | AST only |
| A.cpp:166:20:166:23 | next | AST only |
| A.cpp:166:26:166:29 | next | AST only |
| A.cpp:166:32:166:35 | head | AST only |
| A.cpp:169:12:169:12 | l | AST only |
| A.cpp:167:47:167:50 | l | IR only |
| A.cpp:169:15:169:18 | head | AST only |
| A.cpp:183:7:183:10 | head | AST only |
| A.cpp:184:13:184:16 | next | AST only |
| B.cpp:7:25:7:25 | e | AST only |
| B.cpp:8:25:8:26 | b1 | AST only |
| B.cpp:9:10:9:11 | b2 | AST only |
| B.cpp:9:14:9:17 | box1 | AST only |
| B.cpp:9:20:9:24 | elem1 | AST only |
| B.cpp:10:10:10:11 | b2 | AST only |
| B.cpp:10:14:10:17 | box1 | AST only |
| B.cpp:10:20:10:24 | elem2 | AST only |
| B.cpp:16:37:16:37 | e | AST only |
| B.cpp:17:25:17:26 | b1 | AST only |
| B.cpp:18:10:18:11 | b2 | AST only |
| B.cpp:18:14:18:17 | box1 | AST only |
| B.cpp:18:20:18:24 | elem1 | AST only |
| B.cpp:19:10:19:11 | b2 | AST only |
| B.cpp:19:14:19:17 | box1 | AST only |
| B.cpp:19:20:19:24 | elem2 | AST only |
| B.cpp:35:13:35:17 | elem1 | AST only |
| B.cpp:36:13:36:17 | elem2 | AST only |
| B.cpp:46:13:46:16 | box1 | AST only |
| C.cpp:19:5:19:5 | c | AST only |
| C.cpp:24:11:24:12 | s3 | AST only |
| C.cpp:29:10:29:11 | this | IR only |
| C.cpp:30:10:30:11 | this | IR only |
| C.cpp:31:10:31:11 | this | IR only |
| D.cpp:9:21:9:24 | elem | AST only |
| D.cpp:10:30:10:33 | this | IR only |
| D.cpp:11:29:11:32 | elem | AST only |
| D.cpp:16:21:16:23 | box | AST only |
| D.cpp:17:30:17:32 | this | IR only |
| D.cpp:18:29:18:31 | box | AST only |
| D.cpp:22:10:22:11 | b2 | AST only |
| D.cpp:22:14:22:20 | call to getBox1 | AST only |
| D.cpp:22:25:22:31 | call to getElem | AST only |
| D.cpp:30:5:30:5 | b | AST only |
| D.cpp:30:8:30:10 | box | AST only |
| D.cpp:30:13:30:16 | elem | AST only |
| D.cpp:31:14:31:14 | b | AST only |
| D.cpp:37:5:37:5 | b | AST only |
| D.cpp:37:8:37:10 | box | AST only |
| D.cpp:37:21:37:21 | e | AST only |
| D.cpp:38:14:38:14 | b | AST only |
| D.cpp:44:5:44:5 | b | AST only |
| D.cpp:44:8:44:14 | call to getBox1 | AST only |
| D.cpp:44:19:44:22 | elem | AST only |
| D.cpp:45:14:45:14 | b | AST only |
| D.cpp:51:5:51:5 | b | AST only |
@@ -120,26 +92,14 @@
| D.cpp:51:27:51:27 | e | AST only |
| D.cpp:52:14:52:14 | b | AST only |
| D.cpp:57:5:57:12 | boxfield | AST only |
| D.cpp:58:5:58:12 | boxfield | AST only |
| D.cpp:58:5:58:12 | this | AST only |
| D.cpp:58:15:58:17 | box | AST only |
| D.cpp:58:20:58:23 | elem | AST only |
| D.cpp:59:5:59:7 | this | AST only |
| D.cpp:64:10:64:17 | boxfield | AST only |
| D.cpp:64:10:64:17 | this | AST only |
| D.cpp:64:20:64:22 | box | AST only |
| D.cpp:64:25:64:28 | elem | AST only |
| E.cpp:21:10:21:10 | p | AST only |
| E.cpp:21:13:21:16 | data | AST only |
| E.cpp:21:18:21:23 | buffer | AST only |
| E.cpp:28:21:28:23 | raw | AST only |
| E.cpp:29:21:29:21 | b | AST only |
| E.cpp:29:24:29:29 | buffer | AST only |
| E.cpp:30:21:30:21 | p | AST only |
| E.cpp:30:23:30:26 | data | AST only |
| E.cpp:30:28:30:33 | buffer | AST only |
| E.cpp:31:10:31:12 | raw | AST only |
| E.cpp:32:10:32:10 | b | AST only |
| E.cpp:32:13:32:18 | buffer | AST only |
| E.cpp:33:18:33:19 | & ... | AST only |
| aliasing.cpp:9:6:9:7 | m1 | AST only |
@@ -147,79 +107,92 @@
| aliasing.cpp:17:5:17:6 | m1 | AST only |
| aliasing.cpp:25:17:25:19 | & ... | AST only |
| aliasing.cpp:26:19:26:20 | s2 | AST only |
| aliasing.cpp:29:11:29:12 | s1 | IR only |
| aliasing.cpp:30:11:30:12 | s2 | IR only |
| aliasing.cpp:31:11:31:12 | s3 | IR only |
| aliasing.cpp:37:8:37:9 | m1 | AST only |
| aliasing.cpp:38:11:38:12 | s1 | IR only |
| aliasing.cpp:42:6:42:7 | m1 | AST only |
| aliasing.cpp:43:13:43:14 | ref2 | IR only |
| aliasing.cpp:49:9:49:10 | m1 | AST only |
| aliasing.cpp:50:11:50:12 | s1 | IR only |
| aliasing.cpp:54:6:54:7 | m1 | AST only |
| aliasing.cpp:55:14:55:15 | copy2 | IR only |
| aliasing.cpp:60:6:60:7 | m1 | AST only |
| aliasing.cpp:62:14:62:15 | copy2 | IR only |
| aliasing.cpp:71:11:71:11 | w | IR only |
| aliasing.cpp:72:5:72:6 | m1 | AST only |
| aliasing.cpp:73:10:73:10 | w | IR only |
| aliasing.cpp:73:12:73:13 | s | IR only |
| aliasing.cpp:78:13:78:13 | w | IR only |
| aliasing.cpp:79:6:79:7 | m1 | AST only |
| aliasing.cpp:80:10:80:10 | w | IR only |
| aliasing.cpp:80:12:80:13 | s | IR only |
| aliasing.cpp:85:12:85:12 | w | IR only |
| aliasing.cpp:86:5:86:6 | m1 | AST only |
| aliasing.cpp:92:3:92:3 | w | AST only |
| aliasing.cpp:87:10:87:10 | w | IR only |
| aliasing.cpp:87:12:87:13 | s | IR only |
| aliasing.cpp:92:7:92:8 | m1 | AST only |
| aliasing.cpp:93:10:93:10 | w | IR only |
| aliasing.cpp:93:12:93:13 | s | IR only |
| aliasing.cpp:98:5:98:6 | m1 | AST only |
| aliasing.cpp:101:21:101:22 | s_copy | IR only |
| aliasing.cpp:106:3:106:5 | * ... | AST only |
| aliasing.cpp:111:15:111:19 | & ... | AST only |
| aliasing.cpp:112:10:112:11 | s | IR only |
| aliasing.cpp:121:15:121:16 | xs | AST only |
| aliasing.cpp:126:15:126:20 | ... - ... | AST only |
| aliasing.cpp:131:15:131:16 | xs | AST only |
| aliasing.cpp:136:15:136:17 | + ... | AST only |
| aliasing.cpp:141:15:141:15 | s | AST only |
| aliasing.cpp:141:17:141:20 | data | AST only |
| aliasing.cpp:143:10:143:13 | s | IR only |
| aliasing.cpp:147:15:147:22 | & ... | AST only |
| aliasing.cpp:158:15:158:15 | s | AST only |
| aliasing.cpp:148:13:148:14 | access to array | IR only |
| aliasing.cpp:158:17:158:20 | data | AST only |
| aliasing.cpp:164:15:164:15 | s | AST only |
| aliasing.cpp:159:11:159:14 | s | IR only |
| aliasing.cpp:164:17:164:20 | data | AST only |
| aliasing.cpp:165:10:165:13 | s | IR only |
| aliasing.cpp:175:15:175:22 | & ... | AST only |
| aliasing.cpp:175:16:175:17 | s2 | AST only |
| aliasing.cpp:176:11:176:11 | s2 | IR only |
| aliasing.cpp:176:13:176:14 | s | IR only |
| aliasing.cpp:181:15:181:22 | & ... | AST only |
| aliasing.cpp:181:16:181:17 | s2 | AST only |
| aliasing.cpp:182:11:182:11 | s2 | IR only |
| aliasing.cpp:182:13:182:14 | s | IR only |
| aliasing.cpp:187:15:187:22 | & ... | AST only |
| aliasing.cpp:187:16:187:17 | s2 | AST only |
| aliasing.cpp:189:13:189:13 | s2_2 | IR only |
| aliasing.cpp:189:15:189:16 | s | IR only |
| aliasing.cpp:194:15:194:22 | & ... | AST only |
| aliasing.cpp:194:16:194:17 | s2 | AST only |
| aliasing.cpp:196:13:196:13 | s2_2 | IR only |
| aliasing.cpp:196:15:196:16 | s | IR only |
| aliasing.cpp:200:15:200:24 | & ... | AST only |
| aliasing.cpp:200:16:200:18 | ps2 | AST only |
| aliasing.cpp:201:13:201:13 | ps2 | IR only |
| aliasing.cpp:201:15:201:16 | s | IR only |
| aliasing.cpp:205:15:205:24 | & ... | AST only |
| aliasing.cpp:205:16:205:18 | ps2 | AST only |
| aliasing.cpp:206:13:206:13 | ps2 | IR only |
| aliasing.cpp:206:15:206:16 | s | IR only |
| aliasing.cpp:211:8:211:9 | m1 | AST only |
| aliasing.cpp:212:12:212:12 | s2 | IR only |
| aliasing.cpp:213:10:213:11 | s | IR only |
| aliasing.cpp:218:8:218:9 | m1 | AST only |
| aliasing.cpp:219:12:219:12 | s2 | IR only |
| aliasing.cpp:220:10:220:11 | s | IR only |
| aliasing.cpp:225:15:225:22 | & ... | AST only |
| aliasing.cpp:226:12:226:12 | s2 | IR only |
| aliasing.cpp:227:10:227:11 | s | IR only |
| aliasing.cpp:232:15:232:22 | & ... | AST only |
| aliasing.cpp:233:12:233:12 | s2 | IR only |
| aliasing.cpp:234:10:234:11 | s | IR only |
| arrays.cpp:6:3:6:8 | access to array | AST only |
| arrays.cpp:6:3:6:23 | arr | IR only |
| arrays.cpp:15:3:15:10 | * ... | AST only |
| arrays.cpp:36:3:36:3 | o | AST only |
| arrays.cpp:36:5:36:10 | nested | AST only |
| arrays.cpp:36:19:36:22 | data | AST only |
| arrays.cpp:37:8:37:8 | o | AST only |
| arrays.cpp:37:8:37:22 | access to array | AST only |
| arrays.cpp:37:10:37:15 | nested | AST only |
| arrays.cpp:37:24:37:27 | data | AST only |
| arrays.cpp:38:8:38:8 | o | AST only |
| arrays.cpp:38:8:38:22 | access to array | AST only |
| arrays.cpp:38:10:38:15 | nested | AST only |
| arrays.cpp:38:24:38:27 | data | AST only |
| arrays.cpp:42:3:42:3 | o | AST only |
| arrays.cpp:42:3:42:20 | access to array | AST only |
| arrays.cpp:42:5:42:12 | indirect | AST only |
| arrays.cpp:42:22:42:25 | data | AST only |
| arrays.cpp:43:8:43:8 | o | AST only |
| arrays.cpp:43:8:43:25 | access to array | AST only |
| arrays.cpp:43:10:43:17 | indirect | AST only |
| arrays.cpp:43:27:43:30 | data | AST only |
| arrays.cpp:44:8:44:8 | o | AST only |
| arrays.cpp:44:8:44:25 | access to array | AST only |
| arrays.cpp:44:10:44:17 | indirect | AST only |
| arrays.cpp:44:27:44:30 | data | AST only |
| arrays.cpp:48:3:48:3 | o | AST only |
| arrays.cpp:48:3:48:20 | access to array | AST only |
| arrays.cpp:48:5:48:12 | indirect | AST only |
| arrays.cpp:48:22:48:25 | data | AST only |
| arrays.cpp:49:8:49:8 | o | AST only |
| arrays.cpp:49:8:49:25 | access to array | AST only |
| arrays.cpp:49:10:49:17 | indirect | AST only |
| arrays.cpp:49:27:49:30 | data | AST only |
| arrays.cpp:50:8:50:8 | o | AST only |
| arrays.cpp:50:8:50:25 | access to array | AST only |
| arrays.cpp:50:10:50:17 | indirect | AST only |
| arrays.cpp:50:27:50:30 | data | AST only |
| by_reference.cpp:12:8:12:8 | a | AST only |
| by_reference.cpp:16:11:16:11 | a | AST only |
@@ -227,6 +200,8 @@
| by_reference.cpp:20:23:20:27 | value | AST only |
| by_reference.cpp:24:19:24:22 | this | AST only |
| by_reference.cpp:24:25:24:29 | value | AST only |
| by_reference.cpp:32:15:32:15 | s | IR only |
| by_reference.cpp:36:18:36:18 | this | IR only |
| by_reference.cpp:50:3:50:3 | s | AST only |
| by_reference.cpp:50:17:50:26 | call to user_input | AST only |
| by_reference.cpp:51:10:51:20 | call to getDirectly | AST only |
@@ -244,87 +219,63 @@
| by_reference.cpp:92:3:92:5 | * ... | AST only |
| by_reference.cpp:96:3:96:4 | pa | AST only |
| by_reference.cpp:102:21:102:39 | & ... | AST only |
| by_reference.cpp:103:21:103:25 | outer | AST only |
| by_reference.cpp:103:27:103:35 | inner_ptr | AST only |
| by_reference.cpp:104:15:104:22 | & ... | AST only |
| by_reference.cpp:106:21:106:41 | & ... | AST only |
| by_reference.cpp:107:21:107:26 | pouter | AST only |
| by_reference.cpp:107:29:107:37 | inner_ptr | AST only |
| by_reference.cpp:108:15:108:24 | & ... | AST only |
| by_reference.cpp:110:8:110:12 | outer | AST only |
| by_reference.cpp:110:14:110:25 | inner_nested | AST only |
| by_reference.cpp:110:27:110:27 | a | AST only |
| by_reference.cpp:111:8:111:12 | outer | AST only |
| by_reference.cpp:111:14:111:22 | inner_ptr | AST only |
| by_reference.cpp:111:25:111:25 | a | AST only |
| by_reference.cpp:112:8:112:12 | outer | AST only |
| by_reference.cpp:112:14:112:14 | a | AST only |
| by_reference.cpp:114:8:114:13 | pouter | AST only |
| by_reference.cpp:114:16:114:27 | inner_nested | AST only |
| by_reference.cpp:114:29:114:29 | a | AST only |
| by_reference.cpp:115:8:115:13 | pouter | AST only |
| by_reference.cpp:115:16:115:24 | inner_ptr | AST only |
| by_reference.cpp:115:27:115:27 | a | AST only |
| by_reference.cpp:116:8:116:13 | pouter | AST only |
| by_reference.cpp:116:16:116:16 | a | AST only |
| by_reference.cpp:122:27:122:38 | inner_nested | AST only |
| by_reference.cpp:123:21:123:36 | * ... | AST only |
| by_reference.cpp:123:22:123:26 | outer | AST only |
| by_reference.cpp:124:21:124:21 | a | AST only |
| by_reference.cpp:126:29:126:40 | inner_nested | AST only |
| by_reference.cpp:127:21:127:38 | * ... | AST only |
| by_reference.cpp:127:22:127:27 | pouter | AST only |
| by_reference.cpp:128:23:128:23 | a | AST only |
| by_reference.cpp:130:8:130:12 | outer | AST only |
| by_reference.cpp:130:14:130:25 | inner_nested | AST only |
| by_reference.cpp:130:27:130:27 | a | AST only |
| by_reference.cpp:131:8:131:12 | outer | AST only |
| by_reference.cpp:131:14:131:22 | inner_ptr | AST only |
| by_reference.cpp:131:25:131:25 | a | AST only |
| by_reference.cpp:132:8:132:12 | outer | AST only |
| by_reference.cpp:132:14:132:14 | a | AST only |
| by_reference.cpp:134:8:134:13 | pouter | AST only |
| by_reference.cpp:134:16:134:27 | inner_nested | AST only |
| by_reference.cpp:134:29:134:29 | a | AST only |
| by_reference.cpp:135:8:135:13 | pouter | AST only |
| by_reference.cpp:135:16:135:24 | inner_ptr | AST only |
| by_reference.cpp:135:27:135:27 | a | AST only |
| by_reference.cpp:136:8:136:13 | pouter | AST only |
| by_reference.cpp:136:16:136:16 | a | AST only |
| by_reference.cpp:140:3:140:5 | * ... | AST only |
| by_reference.cpp:145:15:145:16 | & ... | AST only |
| complex.cpp:9:20:9:21 | this | IR only |
| complex.cpp:10:20:10:21 | this | IR only |
| complex.cpp:11:22:11:23 | a_ | AST only |
| complex.cpp:12:22:12:23 | b_ | AST only |
| complex.cpp:42:8:42:8 | b | AST only |
| complex.cpp:42:16:42:16 | f | AST only |
| complex.cpp:43:8:43:8 | b | AST only |
| complex.cpp:43:16:43:16 | f | AST only |
| complex.cpp:53:3:53:4 | b1 | AST only |
| complex.cpp:53:12:53:12 | f | AST only |
| complex.cpp:54:3:54:4 | b2 | AST only |
| complex.cpp:54:12:54:12 | f | AST only |
| complex.cpp:55:3:55:4 | b3 | AST only |
| complex.cpp:55:12:55:12 | f | AST only |
| complex.cpp:56:3:56:4 | b3 | AST only |
| complex.cpp:56:12:56:12 | f | AST only |
| complex.cpp:59:7:59:8 | b1 | AST only |
| complex.cpp:62:7:62:8 | b2 | AST only |
| complex.cpp:65:7:65:8 | b3 | AST only |
| complex.cpp:68:7:68:8 | b4 | AST only |
| conflated.cpp:10:3:10:7 | * ... | AST only |
| conflated.cpp:10:4:10:5 | ra | AST only |
| conflated.cpp:11:12:11:12 | ra | IR only |
| conflated.cpp:19:19:19:21 | raw | AST only |
| conflated.cpp:20:8:20:10 | raw | AST only |
| conflated.cpp:29:3:29:4 | pa | AST only |
| conflated.cpp:29:7:29:7 | x | AST only |
| conflated.cpp:36:3:36:4 | pa | AST only |
| conflated.cpp:30:12:30:12 | pa | IR only |
| conflated.cpp:36:7:36:7 | x | AST only |
| conflated.cpp:37:12:37:12 | pa | IR only |
| conflated.cpp:53:7:53:10 | next | AST only |
| conflated.cpp:54:3:54:4 | ll | AST only |
| conflated.cpp:54:7:54:10 | next | AST only |
| conflated.cpp:54:13:54:13 | y | AST only |
| conflated.cpp:55:12:55:15 | ll | IR only |
| conflated.cpp:55:18:55:18 | next | IR only |
| conflated.cpp:59:35:59:38 | next | AST only |
| conflated.cpp:60:3:60:4 | ll | AST only |
| conflated.cpp:60:7:60:10 | next | AST only |
| conflated.cpp:60:13:60:13 | y | AST only |
| conflated.cpp:61:12:61:15 | ll | IR only |
| conflated.cpp:61:18:61:18 | next | IR only |
| constructors.cpp:18:22:18:23 | this | IR only |
| constructors.cpp:19:22:19:23 | this | IR only |
| constructors.cpp:20:24:20:25 | a_ | AST only |
| constructors.cpp:21:24:21:25 | b_ | AST only |
| constructors.cpp:28:10:28:10 | f | AST only |
@@ -336,68 +287,55 @@
| qualifiers.cpp:9:36:9:36 | a | AST only |
| qualifiers.cpp:12:56:12:56 | a | AST only |
| qualifiers.cpp:13:57:13:57 | a | AST only |
| qualifiers.cpp:18:32:18:36 | this | IR only |
| qualifiers.cpp:22:5:22:9 | outer | AST only |
| qualifiers.cpp:22:11:22:18 | call to getInner | AST only |
| qualifiers.cpp:22:23:22:23 | a | AST only |
| qualifiers.cpp:23:10:23:14 | outer | AST only |
| qualifiers.cpp:23:16:23:20 | inner | AST only |
| qualifiers.cpp:23:23:23:23 | a | AST only |
| qualifiers.cpp:27:5:27:9 | outer | AST only |
| qualifiers.cpp:27:11:27:18 | call to getInner | AST only |
| qualifiers.cpp:27:28:27:37 | call to user_input | AST only |
| qualifiers.cpp:28:10:28:14 | outer | AST only |
| qualifiers.cpp:28:16:28:20 | inner | AST only |
| qualifiers.cpp:28:23:28:23 | a | AST only |
| qualifiers.cpp:32:17:32:21 | outer | AST only |
| qualifiers.cpp:32:23:32:30 | call to getInner | AST only |
| qualifiers.cpp:32:35:32:44 | call to user_input | AST only |
| qualifiers.cpp:33:10:33:14 | outer | AST only |
| qualifiers.cpp:33:16:33:20 | inner | AST only |
| qualifiers.cpp:33:23:33:23 | a | AST only |
| qualifiers.cpp:37:19:37:35 | * ... | AST only |
| qualifiers.cpp:37:20:37:24 | outer | AST only |
| qualifiers.cpp:37:38:37:47 | call to user_input | AST only |
| qualifiers.cpp:38:10:38:14 | outer | AST only |
| qualifiers.cpp:38:16:38:20 | inner | AST only |
| qualifiers.cpp:38:23:38:23 | a | AST only |
| qualifiers.cpp:42:6:42:22 | * ... | AST only |
| qualifiers.cpp:42:7:42:11 | outer | AST only |
| qualifiers.cpp:42:25:42:25 | a | AST only |
| qualifiers.cpp:43:10:43:14 | outer | AST only |
| qualifiers.cpp:43:16:43:20 | inner | AST only |
| qualifiers.cpp:43:23:43:23 | a | AST only |
| qualifiers.cpp:47:6:47:11 | & ... | AST only |
| qualifiers.cpp:47:15:47:22 | call to getInner | AST only |
| qualifiers.cpp:47:27:47:27 | a | AST only |
| qualifiers.cpp:48:10:48:14 | outer | AST only |
| qualifiers.cpp:48:16:48:20 | inner | AST only |
| qualifiers.cpp:48:23:48:23 | a | AST only |
| realistic.cpp:26:5:26:10 | offset | AST only |
| realistic.cpp:42:20:42:20 | o | AST only |
| realistic.cpp:49:9:49:11 | foo | AST only |
| realistic.cpp:49:20:49:22 | baz | AST only |
| realistic.cpp:53:9:53:11 | foo | AST only |
| realistic.cpp:53:9:53:18 | access to array | AST only |
| realistic.cpp:53:20:53:22 | baz | AST only |
| realistic.cpp:53:25:53:33 | userInput | AST only |
| realistic.cpp:53:35:53:43 | bufferLen | AST only |
| realistic.cpp:54:16:54:18 | foo | AST only |
| realistic.cpp:54:16:54:25 | access to array | AST only |
| realistic.cpp:54:27:54:29 | baz | AST only |
| realistic.cpp:54:32:54:40 | userInput | AST only |
| realistic.cpp:54:42:54:47 | buffer | AST only |
| realistic.cpp:55:16:55:18 | foo | IR only |
| realistic.cpp:55:23:55:25 | access to array | IR only |
| realistic.cpp:55:28:55:36 | baz | IR only |
| realistic.cpp:55:38:55:46 | userInput | IR only |
| realistic.cpp:57:92:57:94 | foo | IR only |
| realistic.cpp:57:99:57:101 | access to array | IR only |
| realistic.cpp:57:104:57:112 | baz | IR only |
| realistic.cpp:57:114:57:122 | userInput | IR only |
| realistic.cpp:60:16:60:18 | dst | AST only |
| realistic.cpp:61:21:61:23 | foo | AST only |
| realistic.cpp:61:21:61:30 | access to array | AST only |
| realistic.cpp:61:32:61:34 | baz | AST only |
| realistic.cpp:61:37:61:45 | userInput | AST only |
| realistic.cpp:60:25:60:27 | foo | IR only |
| realistic.cpp:60:32:60:34 | access to array | IR only |
| realistic.cpp:60:37:60:45 | baz | IR only |
| realistic.cpp:60:47:60:52 | userInput | IR only |
| realistic.cpp:60:59:60:61 | foo | IR only |
| realistic.cpp:60:66:60:68 | access to array | IR only |
| realistic.cpp:60:71:60:79 | baz | IR only |
| realistic.cpp:60:81:60:89 | userInput | IR only |
| realistic.cpp:61:47:61:55 | bufferLen | AST only |
| realistic.cpp:65:21:65:23 | foo | AST only |
| realistic.cpp:65:21:65:30 | access to array | AST only |
| realistic.cpp:65:32:65:34 | baz | AST only |
| realistic.cpp:65:37:65:45 | userInput | AST only |
| realistic.cpp:65:47:65:52 | buffer | AST only |
| realistic.cpp:66:21:66:23 | dst | AST only |
| simple.cpp:18:22:18:23 | this | IR only |
| simple.cpp:19:22:19:23 | this | IR only |
| simple.cpp:20:24:20:25 | a_ | AST only |
| simple.cpp:21:24:21:25 | b_ | AST only |
| simple.cpp:28:10:28:10 | f | AST only |
@@ -411,31 +349,24 @@
| simple.cpp:51:9:51:9 | h | AST only |
| simple.cpp:54:9:54:9 | i | AST only |
| simple.cpp:65:7:65:7 | i | AST only |
| simple.cpp:83:9:83:10 | this | AST only |
| simple.cpp:67:13:67:13 | a2 | IR only |
| simple.cpp:79:16:79:17 | this | IR only |
| simple.cpp:79:19:79:20 | f2 | IR only |
| simple.cpp:83:12:83:13 | f1 | AST only |
| simple.cpp:84:14:84:20 | this | AST only |
| simple.cpp:92:7:92:7 | i | AST only |
| struct_init.c:15:8:15:9 | ab | AST only |
| simple.cpp:94:13:94:13 | a2 | IR only |
| simple.cpp:104:9:104:9 | i | AST only |
| simple.cpp:106:13:106:13 | b2 | IR only |
| simple.cpp:106:15:106:15 | a | IR only |
| struct_init.c:15:12:15:12 | a | AST only |
| struct_init.c:16:8:16:9 | ab | AST only |
| struct_init.c:16:12:16:12 | b | AST only |
| struct_init.c:22:8:22:9 | ab | AST only |
| struct_init.c:22:11:22:11 | a | AST only |
| struct_init.c:23:8:23:9 | ab | AST only |
| struct_init.c:23:11:23:11 | b | AST only |
| struct_init.c:24:10:24:12 | & ... | AST only |
| struct_init.c:31:8:31:12 | outer | AST only |
| struct_init.c:31:14:31:21 | nestedAB | AST only |
| struct_init.c:31:23:31:23 | a | AST only |
| struct_init.c:32:8:32:12 | outer | AST only |
| struct_init.c:32:14:32:21 | nestedAB | AST only |
| struct_init.c:32:23:32:23 | b | AST only |
| struct_init.c:33:8:33:12 | outer | AST only |
| struct_init.c:33:14:33:22 | pointerAB | AST only |
| struct_init.c:33:25:33:25 | a | AST only |
| struct_init.c:34:8:34:12 | outer | AST only |
| struct_init.c:34:14:34:22 | pointerAB | AST only |
| struct_init.c:34:25:34:25 | b | AST only |
| struct_init.c:36:10:36:24 | & ... | AST only |
| struct_init.c:46:10:46:14 | outer | AST only |
| struct_init.c:46:16:46:24 | pointerAB | AST only |

View File

@@ -1,72 +1,338 @@
| A.cpp:25:7:25:10 | this |
| A.cpp:27:22:27:25 | this |
| A.cpp:28:23:28:26 | this |
| A.cpp:49:10:49:10 | b |
| A.cpp:65:10:65:11 | b1 |
| A.cpp:66:10:66:11 | b2 |
| A.cpp:74:10:74:11 | b1 |
| A.cpp:75:10:75:11 | b2 |
| A.cpp:100:5:100:6 | c1 |
| A.cpp:107:12:107:13 | c1 |
| A.cpp:120:12:120:13 | c1 |
| A.cpp:132:10:132:10 | b |
| A.cpp:142:7:142:7 | b |
| A.cpp:143:7:143:10 | this |
| A.cpp:152:10:152:10 | d |
| A.cpp:153:10:153:10 | d |
| A.cpp:153:13:153:13 | b |
| A.cpp:154:10:154:10 | b |
| A.cpp:163:10:163:11 | l3 |
| A.cpp:164:10:164:11 | l3 |
| A.cpp:164:14:164:17 | next |
| A.cpp:165:10:165:11 | l3 |
| A.cpp:165:14:165:17 | next |
| A.cpp:165:20:165:23 | next |
| A.cpp:166:10:166:11 | l3 |
| A.cpp:166:14:166:17 | next |
| A.cpp:166:20:166:23 | next |
| A.cpp:166:26:166:29 | next |
| A.cpp:167:44:167:44 | l |
| A.cpp:169:12:169:12 | l |
| A.cpp:183:7:183:10 | this |
| A.cpp:184:7:184:10 | this |
| B.cpp:9:10:9:11 | b2 |
| B.cpp:9:14:9:17 | box1 |
| B.cpp:10:10:10:11 | b2 |
| B.cpp:10:14:10:17 | box1 |
| B.cpp:18:10:18:11 | b2 |
| B.cpp:18:14:18:17 | box1 |
| B.cpp:19:10:19:11 | b2 |
| B.cpp:19:14:19:17 | box1 |
| B.cpp:35:7:35:10 | this |
| B.cpp:36:7:36:10 | this |
| B.cpp:46:7:46:10 | this |
| C.cpp:24:5:24:8 | this |
| C.cpp:29:10:29:11 | this |
| C.cpp:30:10:30:11 | this |
| C.cpp:31:10:31:11 | this |
| D.cpp:9:21:9:24 | this |
| D.cpp:10:30:10:33 | this |
| D.cpp:11:29:11:32 | this |
| D.cpp:16:21:16:23 | this |
| D.cpp:17:30:17:32 | this |
| D.cpp:18:29:18:31 | this |
| D.cpp:30:5:30:5 | b |
| D.cpp:30:8:30:10 | box |
| D.cpp:37:5:37:5 | b |
| D.cpp:44:8:44:14 | call to getBox1 |
| D.cpp:57:5:57:12 | this |
| D.cpp:58:5:58:12 | boxfield |
| D.cpp:58:5:58:12 | this |
| D.cpp:58:15:58:17 | box |
| D.cpp:64:10:64:17 | boxfield |
| D.cpp:64:10:64:17 | this |
| D.cpp:64:20:64:22 | box |
| E.cpp:21:10:21:10 | p |
| E.cpp:21:13:21:16 | data |
| E.cpp:29:21:29:21 | b |
| E.cpp:30:21:30:21 | p |
| E.cpp:30:23:30:26 | data |
| E.cpp:32:10:32:10 | b |
| aliasing.cpp:9:3:9:3 | s |
| aliasing.cpp:13:3:13:3 | s |
| aliasing.cpp:17:3:17:3 | s |
| aliasing.cpp:29:8:29:9 | s1 |
| aliasing.cpp:30:8:30:9 | s2 |
| aliasing.cpp:31:8:31:9 | s3 |
| aliasing.cpp:37:3:37:6 | ref1 |
| aliasing.cpp:38:8:38:9 | s1 |
| aliasing.cpp:42:3:42:4 | s2 |
| aliasing.cpp:43:8:43:11 | ref2 |
| aliasing.cpp:49:3:49:7 | copy1 |
| aliasing.cpp:50:8:50:9 | s1 |
| aliasing.cpp:54:3:54:4 | s2 |
| aliasing.cpp:55:8:55:12 | copy2 |
| aliasing.cpp:60:3:60:4 | s2 |
| aliasing.cpp:62:8:62:12 | copy2 |
| aliasing.cpp:71:9:71:9 | w |
| aliasing.cpp:72:3:72:3 | s |
| aliasing.cpp:73:8:73:8 | w |
| aliasing.cpp:73:10:73:10 | s |
| aliasing.cpp:78:11:78:11 | w |
| aliasing.cpp:79:3:79:3 | s |
| aliasing.cpp:80:8:80:8 | w |
| aliasing.cpp:80:10:80:10 | s |
| aliasing.cpp:85:10:85:10 | w |
| aliasing.cpp:86:3:86:3 | s |
| aliasing.cpp:87:8:87:8 | w |
| aliasing.cpp:87:10:87:10 | s |
| aliasing.cpp:92:3:92:3 | w |
| aliasing.cpp:92:5:92:5 | s |
| aliasing.cpp:93:8:93:8 | w |
| aliasing.cpp:93:10:93:10 | s |
| aliasing.cpp:98:3:98:3 | s |
| aliasing.cpp:101:14:101:19 | s_copy |
| aliasing.cpp:111:16:111:16 | s |
| aliasing.cpp:112:8:112:8 | s |
| aliasing.cpp:141:15:141:15 | s |
| aliasing.cpp:143:8:143:8 | s |
| aliasing.cpp:147:16:147:19 | access to array |
| aliasing.cpp:148:8:148:11 | access to array |
| aliasing.cpp:158:15:158:15 | s |
| aliasing.cpp:159:9:159:9 | s |
| aliasing.cpp:164:15:164:15 | s |
| aliasing.cpp:165:8:165:8 | s |
| aliasing.cpp:175:16:175:17 | s2 |
| aliasing.cpp:175:19:175:19 | s |
| aliasing.cpp:176:8:176:9 | s2 |
| aliasing.cpp:176:11:176:11 | s |
| aliasing.cpp:181:16:181:17 | s2 |
| aliasing.cpp:181:19:181:19 | s |
| aliasing.cpp:182:8:182:9 | s2 |
| aliasing.cpp:182:11:182:11 | s |
| aliasing.cpp:187:16:187:17 | s2 |
| aliasing.cpp:187:19:187:19 | s |
| aliasing.cpp:189:8:189:11 | s2_2 |
| aliasing.cpp:189:13:189:13 | s |
| aliasing.cpp:194:16:194:17 | s2 |
| aliasing.cpp:194:19:194:19 | s |
| aliasing.cpp:196:8:196:11 | s2_2 |
| aliasing.cpp:196:13:196:13 | s |
| aliasing.cpp:200:16:200:18 | ps2 |
| aliasing.cpp:200:21:200:21 | s |
| aliasing.cpp:201:8:201:10 | ps2 |
| aliasing.cpp:201:13:201:13 | s |
| aliasing.cpp:205:16:205:18 | ps2 |
| aliasing.cpp:205:21:205:21 | s |
| aliasing.cpp:206:8:206:10 | ps2 |
| aliasing.cpp:206:13:206:13 | s |
| aliasing.cpp:211:3:211:4 | s2 |
| aliasing.cpp:211:6:211:6 | s |
| aliasing.cpp:212:9:212:10 | s2 |
| aliasing.cpp:213:8:213:8 | s |
| aliasing.cpp:218:3:218:4 | s2 |
| aliasing.cpp:218:6:218:6 | s |
| aliasing.cpp:219:9:219:10 | s2 |
| aliasing.cpp:220:8:220:8 | s |
| aliasing.cpp:225:16:225:17 | s2 |
| aliasing.cpp:225:19:225:19 | s |
| aliasing.cpp:226:9:226:10 | s2 |
| aliasing.cpp:227:8:227:8 | s |
| aliasing.cpp:232:16:232:17 | s2 |
| aliasing.cpp:232:19:232:19 | s |
| aliasing.cpp:233:9:233:10 | s2 |
| aliasing.cpp:234:8:234:8 | s |
| arrays.cpp:6:3:6:5 | arr |
| arrays.cpp:36:3:36:3 | o |
| arrays.cpp:36:3:36:17 | access to array |
| arrays.cpp:36:5:36:10 | nested |
| arrays.cpp:37:8:37:8 | o |
| arrays.cpp:37:8:37:22 | access to array |
| arrays.cpp:37:10:37:15 | nested |
| arrays.cpp:38:8:38:8 | o |
| arrays.cpp:38:8:38:22 | access to array |
| arrays.cpp:38:10:38:15 | nested |
| arrays.cpp:42:3:42:3 | o |
| arrays.cpp:42:3:42:20 | access to array |
| arrays.cpp:42:5:42:12 | indirect |
| arrays.cpp:43:8:43:8 | o |
| arrays.cpp:43:8:43:25 | access to array |
| arrays.cpp:43:10:43:17 | indirect |
| arrays.cpp:44:8:44:8 | o |
| arrays.cpp:44:8:44:25 | access to array |
| arrays.cpp:44:10:44:17 | indirect |
| arrays.cpp:48:3:48:3 | o |
| arrays.cpp:48:3:48:20 | access to array |
| arrays.cpp:48:5:48:12 | indirect |
| arrays.cpp:49:8:49:8 | o |
| arrays.cpp:49:8:49:25 | access to array |
| arrays.cpp:49:10:49:17 | indirect |
| arrays.cpp:50:8:50:8 | o |
| arrays.cpp:50:8:50:25 | access to array |
| arrays.cpp:50:10:50:17 | indirect |
| by_reference.cpp:12:5:12:5 | s |
| by_reference.cpp:16:5:16:8 | this |
| by_reference.cpp:32:12:32:12 | s |
| by_reference.cpp:36:12:36:15 | this |
| by_reference.cpp:84:3:84:7 | inner |
| by_reference.cpp:88:3:88:7 | inner |
| by_reference.cpp:102:22:102:26 | outer |
| by_reference.cpp:103:21:103:25 | outer |
| by_reference.cpp:104:16:104:20 | outer |
| by_reference.cpp:106:22:106:27 | pouter |
| by_reference.cpp:107:21:107:26 | pouter |
| by_reference.cpp:108:16:108:21 | pouter |
| by_reference.cpp:110:8:110:12 | outer |
| by_reference.cpp:110:14:110:25 | inner_nested |
| by_reference.cpp:111:8:111:12 | outer |
| by_reference.cpp:111:14:111:22 | inner_ptr |
| by_reference.cpp:112:8:112:12 | outer |
| by_reference.cpp:114:8:114:13 | pouter |
| by_reference.cpp:114:16:114:27 | inner_nested |
| by_reference.cpp:115:8:115:13 | pouter |
| by_reference.cpp:115:16:115:24 | inner_ptr |
| by_reference.cpp:116:8:116:13 | pouter |
| by_reference.cpp:122:21:122:25 | outer |
| by_reference.cpp:123:22:123:26 | outer |
| by_reference.cpp:124:15:124:19 | outer |
| by_reference.cpp:126:21:126:26 | pouter |
| by_reference.cpp:127:22:127:27 | pouter |
| by_reference.cpp:128:15:128:20 | pouter |
| by_reference.cpp:130:8:130:12 | outer |
| by_reference.cpp:130:14:130:25 | inner_nested |
| by_reference.cpp:131:8:131:12 | outer |
| by_reference.cpp:131:14:131:22 | inner_ptr |
| by_reference.cpp:132:8:132:12 | outer |
| by_reference.cpp:134:8:134:13 | pouter |
| by_reference.cpp:134:16:134:27 | inner_nested |
| by_reference.cpp:135:8:135:13 | pouter |
| by_reference.cpp:135:16:135:24 | inner_ptr |
| by_reference.cpp:136:8:136:13 | pouter |
| complex.cpp:9:20:9:21 | this |
| complex.cpp:10:20:10:21 | this |
| complex.cpp:11:22:11:23 | this |
| complex.cpp:12:22:12:23 | this |
| complex.cpp:42:8:42:8 | b |
| complex.cpp:42:10:42:14 | inner |
| complex.cpp:43:8:43:8 | b |
| complex.cpp:43:10:43:14 | inner |
| complex.cpp:53:3:53:4 | b1 |
| complex.cpp:53:6:53:10 | inner |
| complex.cpp:54:3:54:4 | b2 |
| complex.cpp:54:6:54:10 | inner |
| complex.cpp:55:3:55:4 | b3 |
| complex.cpp:55:6:55:10 | inner |
| complex.cpp:56:3:56:4 | b3 |
| complex.cpp:56:6:56:10 | inner |
| conflated.cpp:10:4:10:5 | ra |
| conflated.cpp:11:9:11:10 | ra |
| conflated.cpp:29:3:29:4 | pa |
| conflated.cpp:30:8:30:9 | pa |
| conflated.cpp:36:3:36:4 | pa |
| conflated.cpp:37:8:37:9 | pa |
| conflated.cpp:53:3:53:4 | ll |
| conflated.cpp:54:3:54:4 | ll |
| conflated.cpp:54:7:54:10 | next |
| conflated.cpp:55:8:55:9 | ll |
| conflated.cpp:55:12:55:15 | next |
| conflated.cpp:60:3:60:4 | ll |
| conflated.cpp:60:7:60:10 | next |
| conflated.cpp:61:8:61:9 | ll |
| conflated.cpp:61:12:61:15 | next |
| constructors.cpp:18:22:18:23 | this |
| constructors.cpp:19:22:19:23 | this |
| constructors.cpp:20:24:20:25 | this |
| constructors.cpp:21:24:21:25 | this |
| qualifiers.cpp:9:30:9:33 | this |
| qualifiers.cpp:12:49:12:53 | inner |
| qualifiers.cpp:13:51:13:55 | inner |
| qualifiers.cpp:18:32:18:36 | this |
| qualifiers.cpp:22:11:22:18 | call to getInner |
| qualifiers.cpp:23:10:23:14 | outer |
| qualifiers.cpp:23:16:23:20 | inner |
| qualifiers.cpp:28:10:28:14 | outer |
| qualifiers.cpp:28:16:28:20 | inner |
| qualifiers.cpp:33:10:33:14 | outer |
| qualifiers.cpp:33:16:33:20 | inner |
| qualifiers.cpp:38:10:38:14 | outer |
| qualifiers.cpp:38:16:38:20 | inner |
| qualifiers.cpp:42:6:42:22 | * ... |
| qualifiers.cpp:43:10:43:14 | outer |
| qualifiers.cpp:43:16:43:20 | inner |
| qualifiers.cpp:47:15:47:22 | call to getInner |
| qualifiers.cpp:48:10:48:14 | outer |
| qualifiers.cpp:48:16:48:20 | inner |
| realistic.cpp:49:9:49:11 | foo |
| realistic.cpp:49:9:49:18 | access to array |
| realistic.cpp:53:9:53:11 | foo |
| realistic.cpp:53:9:53:18 | access to array |
| realistic.cpp:53:20:53:22 | baz |
| realistic.cpp:53:25:53:33 | userInput |
| realistic.cpp:54:16:54:18 | foo |
| realistic.cpp:54:16:54:25 | access to array |
| realistic.cpp:54:27:54:29 | baz |
| realistic.cpp:54:32:54:40 | userInput |
| realistic.cpp:55:12:55:14 | foo |
| realistic.cpp:55:12:55:21 | access to array |
| realistic.cpp:55:23:55:25 | baz |
| realistic.cpp:55:28:55:36 | userInput |
| realistic.cpp:57:88:57:90 | foo |
| realistic.cpp:57:88:57:97 | access to array |
| realistic.cpp:57:99:57:101 | baz |
| realistic.cpp:57:104:57:112 | userInput |
| realistic.cpp:60:21:60:23 | foo |
| realistic.cpp:60:21:60:30 | access to array |
| realistic.cpp:60:32:60:34 | baz |
| realistic.cpp:60:37:60:45 | userInput |
| realistic.cpp:60:55:60:57 | foo |
| realistic.cpp:60:55:60:64 | access to array |
| realistic.cpp:60:66:60:68 | baz |
| realistic.cpp:60:71:60:79 | userInput |
| realistic.cpp:61:21:61:23 | foo |
| realistic.cpp:61:21:61:30 | access to array |
| realistic.cpp:61:32:61:34 | baz |
| realistic.cpp:61:37:61:45 | userInput |
| realistic.cpp:65:21:65:23 | foo |
| realistic.cpp:65:21:65:30 | access to array |
| realistic.cpp:65:32:65:34 | baz |
| realistic.cpp:65:37:65:45 | userInput |
| simple.cpp:18:22:18:23 | this |
| simple.cpp:19:22:19:23 | this |
| simple.cpp:20:24:20:25 | this |
| simple.cpp:21:24:21:25 | this |
| simple.cpp:65:5:65:5 | a |
| simple.cpp:67:10:67:11 | a2 |
| simple.cpp:79:16:79:17 | f2 |
| simple.cpp:79:16:79:17 | this |
| simple.cpp:83:9:83:10 | f2 |
| simple.cpp:83:9:83:10 | this |
| simple.cpp:92:5:92:5 | a |
| simple.cpp:94:10:94:11 | a2 |
| simple.cpp:104:5:104:5 | b |
| simple.cpp:104:7:104:7 | a |
| simple.cpp:106:10:106:11 | b2 |
| simple.cpp:106:13:106:13 | a |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:16:8:16:9 | ab |
| struct_init.c:22:8:22:9 | ab |
| struct_init.c:23:8:23:9 | ab |
| struct_init.c:31:8:31:12 | outer |
| struct_init.c:31:14:31:21 | nestedAB |
| struct_init.c:32:8:32:12 | outer |
| struct_init.c:32:14:32:21 | nestedAB |
| struct_init.c:33:8:33:12 | outer |
| struct_init.c:33:14:33:22 | pointerAB |
| struct_init.c:34:8:34:12 | outer |
| struct_init.c:34:14:34:22 | pointerAB |
| struct_init.c:36:11:36:15 | outer |
| struct_init.c:46:10:46:14 | outer |

View File

@@ -220,6 +220,18 @@
| aliasing.cpp:205:15:205:24 | & ... |
| aliasing.cpp:205:16:205:18 | ps2 |
| aliasing.cpp:205:21:205:21 | s |
| aliasing.cpp:211:3:211:4 | s2 |
| aliasing.cpp:211:6:211:6 | s |
| aliasing.cpp:211:8:211:9 | m1 |
| aliasing.cpp:218:3:218:4 | s2 |
| aliasing.cpp:218:6:218:6 | s |
| aliasing.cpp:218:8:218:9 | m1 |
| aliasing.cpp:225:15:225:22 | & ... |
| aliasing.cpp:225:16:225:17 | s2 |
| aliasing.cpp:225:19:225:19 | s |
| aliasing.cpp:232:15:232:22 | & ... |
| aliasing.cpp:232:16:232:17 | s2 |
| aliasing.cpp:232:19:232:19 | s |
| arrays.cpp:6:3:6:8 | access to array |
| arrays.cpp:15:3:15:10 | * ... |
| arrays.cpp:36:3:36:3 | o |
@@ -340,6 +352,8 @@
| by_reference.cpp:135:27:135:27 | a |
| by_reference.cpp:136:8:136:13 | pouter |
| by_reference.cpp:136:16:136:16 | a |
| by_reference.cpp:140:3:140:5 | * ... |
| by_reference.cpp:145:15:145:16 | & ... |
| complex.cpp:11:22:11:23 | a_ |
| complex.cpp:11:22:11:23 | this |
| complex.cpp:12:22:12:23 | b_ |
@@ -484,6 +498,9 @@
| simple.cpp:84:14:84:20 | this |
| simple.cpp:92:5:92:5 | a |
| simple.cpp:92:7:92:7 | i |
| simple.cpp:104:5:104:5 | b |
| simple.cpp:104:7:104:7 | a |
| simple.cpp:104:9:104:9 | i |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:15:12:15:12 | a |
| struct_init.c:16:8:16:9 | ab |

View File

@@ -160,6 +160,7 @@ edges
| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:175:15:175:22 | ref arg & ... |
| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:187:15:187:22 | ref arg & ... |
| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:200:15:200:24 | ref arg & ... |
| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:225:15:225:22 | ref arg & ... |
| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:4:106:5 | pa [inner post update] |
| aliasing.cpp:158:15:158:15 | s [post update] [data] | aliasing.cpp:159:9:159:9 | s [data] |
| aliasing.cpp:158:17:158:20 | ref arg data | aliasing.cpp:158:15:158:15 | s [post update] [data] |
@@ -187,6 +188,20 @@ edges
| aliasing.cpp:200:23:200:24 | m1 [inner post update] | aliasing.cpp:200:21:200:21 | s [post update] [m1] |
| aliasing.cpp:201:8:201:10 | ps2 [s, m1] | aliasing.cpp:201:13:201:13 | s [m1] |
| aliasing.cpp:201:13:201:13 | s [m1] | aliasing.cpp:201:15:201:16 | m1 |
| aliasing.cpp:211:3:211:4 | s2 [post update] [s, m1] | aliasing.cpp:212:9:212:10 | s2 [s, m1] |
| aliasing.cpp:211:3:211:24 | ... = ... | aliasing.cpp:211:6:211:6 | s [post update] [m1] |
| aliasing.cpp:211:6:211:6 | s [post update] [m1] | aliasing.cpp:211:3:211:4 | s2 [post update] [s, m1] |
| aliasing.cpp:211:13:211:22 | call to user_input | aliasing.cpp:211:3:211:24 | ... = ... |
| aliasing.cpp:212:9:212:10 | s2 [s, m1] | aliasing.cpp:212:12:212:12 | s [m1] |
| aliasing.cpp:212:12:212:12 | s [m1] | aliasing.cpp:213:8:213:8 | s [m1] |
| aliasing.cpp:213:8:213:8 | s [m1] | aliasing.cpp:213:10:213:11 | m1 |
| aliasing.cpp:225:15:225:22 | ref arg & ... | aliasing.cpp:225:21:225:22 | m1 [inner post update] |
| aliasing.cpp:225:16:225:17 | s2 [post update] [s, m1] | aliasing.cpp:226:9:226:10 | s2 [s, m1] |
| aliasing.cpp:225:19:225:19 | s [post update] [m1] | aliasing.cpp:225:16:225:17 | s2 [post update] [s, m1] |
| aliasing.cpp:225:21:225:22 | m1 [inner post update] | aliasing.cpp:225:19:225:19 | s [post update] [m1] |
| aliasing.cpp:226:9:226:10 | s2 [s, m1] | aliasing.cpp:226:12:226:12 | s [m1] |
| aliasing.cpp:226:12:226:12 | s [m1] | aliasing.cpp:227:8:227:8 | s [m1] |
| aliasing.cpp:227:8:227:8 | s [m1] | aliasing.cpp:227:10:227:11 | m1 |
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array |
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:8:8:8:13 | access to array |
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... |
@@ -308,6 +323,9 @@ edges
| by_reference.cpp:135:8:135:13 | pouter [inner_ptr, a] | by_reference.cpp:135:16:135:24 | inner_ptr [a] |
| by_reference.cpp:135:16:135:24 | inner_ptr [a] | by_reference.cpp:135:27:135:27 | a |
| by_reference.cpp:136:8:136:13 | pouter [a] | by_reference.cpp:136:16:136:16 | a |
| by_reference.cpp:140:4:140:5 | pa [inner post update] | by_reference.cpp:145:15:145:16 | ref arg & ... |
| by_reference.cpp:140:16:140:25 | call to user_input | by_reference.cpp:140:4:140:5 | pa [inner post update] |
| by_reference.cpp:145:15:145:16 | ref arg & ... | by_reference.cpp:146:8:146:8 | s |
| complex.cpp:40:17:40:17 | b [inner, f, a_] | complex.cpp:42:8:42:8 | b [inner, f, a_] |
| complex.cpp:40:17:40:17 | b [inner, f, b_] | complex.cpp:43:8:43:8 | b [inner, f, b_] |
| complex.cpp:42:8:42:8 | b [inner, f, a_] | complex.cpp:42:10:42:14 | inner [f, a_] |
@@ -449,6 +467,12 @@ edges
| simple.cpp:92:5:92:22 | ... = ... | simple.cpp:92:5:92:5 | a [post update] [i] |
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | ... = ... |
| simple.cpp:94:10:94:11 | a2 [i] | simple.cpp:94:13:94:13 | i |
| simple.cpp:104:5:104:5 | b [post update] [a, i] | simple.cpp:106:10:106:11 | b2 [a, i] |
| simple.cpp:104:5:104:24 | ... = ... | simple.cpp:104:7:104:7 | a [post update] [i] |
| simple.cpp:104:7:104:7 | a [post update] [i] | simple.cpp:104:5:104:5 | b [post update] [a, i] |
| simple.cpp:104:13:104:22 | call to user_input | simple.cpp:104:5:104:24 | ... = ... |
| simple.cpp:106:10:106:11 | b2 [a, i] | simple.cpp:106:13:106:13 | a [i] |
| simple.cpp:106:13:106:13 | a [i] | simple.cpp:106:15:106:15 | i |
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [a] |
| struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:17:20:36 | {...} [a] | struct_init.c:22:8:22:9 | ab [a] |
@@ -689,6 +713,22 @@ nodes
| aliasing.cpp:201:8:201:10 | ps2 [s, m1] | semmle.label | ps2 [s, m1] |
| aliasing.cpp:201:13:201:13 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:201:15:201:16 | m1 | semmle.label | m1 |
| aliasing.cpp:211:3:211:4 | s2 [post update] [s, m1] | semmle.label | s2 [post update] [s, m1] |
| aliasing.cpp:211:3:211:24 | ... = ... | semmle.label | ... = ... |
| aliasing.cpp:211:6:211:6 | s [post update] [m1] | semmle.label | s [post update] [m1] |
| aliasing.cpp:211:13:211:22 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:212:9:212:10 | s2 [s, m1] | semmle.label | s2 [s, m1] |
| aliasing.cpp:212:12:212:12 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:213:8:213:8 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:213:10:213:11 | m1 | semmle.label | m1 |
| aliasing.cpp:225:15:225:22 | ref arg & ... | semmle.label | ref arg & ... |
| aliasing.cpp:225:16:225:17 | s2 [post update] [s, m1] | semmle.label | s2 [post update] [s, m1] |
| aliasing.cpp:225:19:225:19 | s [post update] [m1] | semmle.label | s [post update] [m1] |
| aliasing.cpp:225:21:225:22 | m1 [inner post update] | semmle.label | m1 [inner post update] |
| aliasing.cpp:226:9:226:10 | s2 [s, m1] | semmle.label | s2 [s, m1] |
| aliasing.cpp:226:12:226:12 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:227:8:227:8 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:227:10:227:11 | m1 | semmle.label | m1 |
| arrays.cpp:6:12:6:21 | call to user_input | semmle.label | call to user_input |
| arrays.cpp:7:8:7:13 | access to array | semmle.label | access to array |
| arrays.cpp:8:8:8:13 | access to array | semmle.label | access to array |
@@ -818,6 +858,10 @@ nodes
| by_reference.cpp:135:27:135:27 | a | semmle.label | a |
| by_reference.cpp:136:8:136:13 | pouter [a] | semmle.label | pouter [a] |
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
| by_reference.cpp:140:4:140:5 | pa [inner post update] | semmle.label | pa [inner post update] |
| by_reference.cpp:140:16:140:25 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:145:15:145:16 | ref arg & ... | semmle.label | ref arg & ... |
| by_reference.cpp:146:8:146:8 | s | semmle.label | s |
| complex.cpp:40:17:40:17 | b [inner, f, a_] | semmle.label | b [inner, f, a_] |
| complex.cpp:40:17:40:17 | b [inner, f, b_] | semmle.label | b [inner, f, b_] |
| complex.cpp:42:8:42:8 | b [inner, f, a_] | semmle.label | b [inner, f, a_] |
@@ -980,6 +1024,13 @@ nodes
| simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:94:10:94:11 | a2 [i] | semmle.label | a2 [i] |
| simple.cpp:94:13:94:13 | i | semmle.label | i |
| simple.cpp:104:5:104:5 | b [post update] [a, i] | semmle.label | b [post update] [a, i] |
| simple.cpp:104:5:104:24 | ... = ... | semmle.label | ... = ... |
| simple.cpp:104:7:104:7 | a [post update] [i] | semmle.label | a [post update] [i] |
| simple.cpp:104:13:104:22 | call to user_input | semmle.label | call to user_input |
| simple.cpp:106:10:106:11 | b2 [a, i] | semmle.label | b2 [a, i] |
| simple.cpp:106:13:106:13 | a [i] | semmle.label | a [i] |
| simple.cpp:106:15:106:15 | i | semmle.label | i |
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
| struct_init.c:15:8:15:9 | ab [a] | semmle.label | ab [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
@@ -1045,6 +1096,8 @@ nodes
| aliasing.cpp:176:13:176:14 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:176:13:176:14 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input |
| aliasing.cpp:189:15:189:16 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:189:15:189:16 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input |
| aliasing.cpp:201:15:201:16 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:201:15:201:16 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input |
| aliasing.cpp:213:10:213:11 | m1 | aliasing.cpp:211:13:211:22 | call to user_input | aliasing.cpp:213:10:213:11 | m1 | m1 flows from $@ | aliasing.cpp:211:13:211:22 | call to user_input | call to user_input |
| aliasing.cpp:227:10:227:11 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:227:10:227:11 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input |
| arrays.cpp:7:8:7:13 | access to array | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array | access to array flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
| arrays.cpp:8:8:8:13 | access to array | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:8:8:8:13 | access to array | access to array flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
| arrays.cpp:9:8:9:11 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
@@ -1071,6 +1124,7 @@ nodes
| by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:135:27:135:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:135:27:135:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:136:16:136:16 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:136:16:136:16 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input |
| by_reference.cpp:146:8:146:8 | s | by_reference.cpp:140:16:140:25 | call to user_input | by_reference.cpp:146:8:146:8 | s | s flows from $@ | by_reference.cpp:140:16:140:25 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:53:19:53:28 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:55:19:55:28 | call to user_input | call to user_input |
| complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input |
@@ -1098,6 +1152,7 @@ nodes
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
| simple.cpp:106:15:106:15 | i | simple.cpp:104:13:104:22 | call to user_input | simple.cpp:106:15:106:15 | i | i flows from $@ | simple.cpp:104:13:104:22 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input |

View File

@@ -94,4 +94,16 @@ void single_field_test_typedef(A_typedef a)
sink(a2.i); //$ ast,ir
}
struct B {
A a;
};
void single_field_test_depth_2()
{
B b;
b.a.i = user_input();
B b2 = b;
sink(b2.a.i); //$ ast MISSING: ir
}
} // namespace Simple

View File

@@ -0,0 +1,47 @@
int source();
void sink(...);
class MyValue
{
public:
MyValue(int _x) : x(_x) {}; // taint flows from parameter `_x` to member variable `x`
MyValue(int _x, bool ex) : MyValue(_x) {}; // taint flows from parameter `_x` to member variable `x`
MyValue(int _x, int _y) : MyValue(_x + _y) {}; // taint flows from parameters `_x` and `_y` to member variable `x`
MyValue(int _x, bool ex1, bool ex2) : MyValue(0) {}; // taint doesn't flow from parameter `_x`
int x;
};
class MyDerivedValue : public MyValue
{
public:
MyDerivedValue(bool ex, int _x) : MyValue(_x) {}; // taint flows from parameter `_x` to member variable `x`
};
void test_inits()
{
MyValue v1(0);
MyValue v2(source());
MyValue v3(0, true);
MyValue v4(source(), true);
MyValue v5(0, 1);
MyValue v6(source(), 1);
MyValue v7(0, source());
MyValue v8(0, true, true);
MyValue v9(source(), true, true);
MyDerivedValue v10(true, 0);
MyDerivedValue v11(true, source());
sink(v1.x);
sink(v2.x); // $ ast,ir
sink(v3.x);
sink(v4.x); // $ ir MISSING: ast
sink(v5.x);
sink(v6.x); // $ ir MISSING: ast
sink(v7.x); // $ ir MISSING: ast
sink(v8.x);
sink(v9.x);
sink(v10.x);
sink(v11.x); // $ ir MISSING: ast
}

View File

@@ -135,6 +135,28 @@
| arrayassignment.cpp:145:12:145:12 | 5 | arrayassignment.cpp:145:7:145:13 | access to array | TAINT |
| arrayassignment.cpp:146:7:146:10 | arr3 | arrayassignment.cpp:146:7:146:13 | access to array | |
| arrayassignment.cpp:146:12:146:12 | 5 | arrayassignment.cpp:146:7:146:13 | access to array | TAINT |
| constructor_delegation.cpp:8:2:8:8 | this | constructor_delegation.cpp:8:20:8:24 | constructor init of field x [pre-this] | |
| constructor_delegation.cpp:8:14:8:15 | _x | constructor_delegation.cpp:8:22:8:23 | _x | |
| constructor_delegation.cpp:8:22:8:23 | _x | constructor_delegation.cpp:8:20:8:24 | constructor init of field x | TAINT |
| constructor_delegation.cpp:9:37:9:38 | _x | constructor_delegation.cpp:9:29:9:39 | call to MyValue | TAINT |
| constructor_delegation.cpp:10:36:10:37 | _x | constructor_delegation.cpp:10:36:10:42 | ... + ... | TAINT |
| constructor_delegation.cpp:10:36:10:42 | ... + ... | constructor_delegation.cpp:10:28:10:43 | call to MyValue | TAINT |
| constructor_delegation.cpp:10:41:10:42 | _y | constructor_delegation.cpp:10:36:10:42 | ... + ... | TAINT |
| constructor_delegation.cpp:11:48:11:48 | 0 | constructor_delegation.cpp:11:40:11:49 | call to MyValue | TAINT |
| constructor_delegation.cpp:19:44:19:45 | _x | constructor_delegation.cpp:19:36:19:46 | call to MyValue | TAINT |
| constructor_delegation.cpp:24:13:24:13 | 0 | constructor_delegation.cpp:24:13:24:14 | call to MyValue | TAINT |
| constructor_delegation.cpp:24:13:24:14 | call to MyValue | constructor_delegation.cpp:36:7:36:8 | v1 | |
| constructor_delegation.cpp:25:13:25:18 | call to source | constructor_delegation.cpp:25:13:25:21 | call to MyValue | TAINT |
| constructor_delegation.cpp:25:13:25:21 | call to MyValue | constructor_delegation.cpp:37:7:37:8 | v2 | |
| constructor_delegation.cpp:26:13:26:20 | call to MyValue | constructor_delegation.cpp:38:7:38:8 | v3 | |
| constructor_delegation.cpp:27:13:27:27 | call to MyValue | constructor_delegation.cpp:39:7:39:8 | v4 | |
| constructor_delegation.cpp:28:13:28:17 | call to MyValue | constructor_delegation.cpp:40:7:40:8 | v5 | |
| constructor_delegation.cpp:29:13:29:24 | call to MyValue | constructor_delegation.cpp:41:7:41:8 | v6 | |
| constructor_delegation.cpp:30:13:30:24 | call to MyValue | constructor_delegation.cpp:42:7:42:8 | v7 | |
| constructor_delegation.cpp:31:13:31:26 | call to MyValue | constructor_delegation.cpp:43:7:43:8 | v8 | |
| constructor_delegation.cpp:32:13:32:33 | call to MyValue | constructor_delegation.cpp:44:7:44:8 | v9 | |
| constructor_delegation.cpp:33:21:33:28 | call to MyDerivedValue | constructor_delegation.cpp:45:7:45:9 | v10 | |
| constructor_delegation.cpp:34:21:34:35 | call to MyDerivedValue | constructor_delegation.cpp:46:7:46:9 | v11 | |
| copyableclass.cpp:8:2:8:16 | this | copyableclass.cpp:8:28:8:32 | constructor init of field v [pre-this] | |
| copyableclass.cpp:8:22:8:23 | _v | copyableclass.cpp:8:30:8:31 | _v | |
| copyableclass.cpp:8:30:8:31 | _v | copyableclass.cpp:8:28:8:32 | constructor init of field v | TAINT |

View File

@@ -38,13 +38,13 @@ public:
void test_typedefs(int_iterator_by_typedefs source1) {
sink(*source1); // $ ast,ir
sink(*(source1++)); // $ ast MISSING: ir
sink(*(source1++)); // $ ast,ir
sink(*(++source1)); // $ ast MISSING: ir
}
void test_trait(int_iterator_by_trait source1) {
sink(*source1); // $ ast,ir
sink(*(source1++)); // $ ast MISSING: ir
sink(*(source1++)); // $ ast,ir
sink(*(++source1)); // $ ast MISSING: ir
}

View File

@@ -415,10 +415,10 @@ void test_string_iterators() {
sink(*i9); // $ ast,ir
i10 = i2;
sink(*(i10++)); // $ ast MISSING: ir
sink(*(i10++)); // $ ast,ir
sink(i10); // $ ast,ir
i11 = i2;
sink(*(i11--)); // $ ast MISSING: ir
sink(*(i11--)); // $ ast,ir
sink(i11); // $ ast,ir
}
}

View File

@@ -75,7 +75,7 @@ void test_stringstream_int(int source)
sink(ss1 << 1234);
sink(ss2 << source); // $ ast MISSING: ir
sink(ss1 >> v1);
sink(ss2 >> v2); // $ ast MISSING: ir
sink(ss2 >> v2); // $ ast,ir
sink(ss1);
sink(ss2); // $ ast,ir
@@ -143,27 +143,27 @@ void test_stringstream_in()
sink(ss2 << source()); // $ ast,ir
sink(ss1 >> s1);
sink(ss2 >> s2); // $ ast MISSING: ir
sink(ss2 >> s3 >> s4); // $ ast MISSING: ir
sink(ss2 >> s2); // $ ast,ir
sink(ss2 >> s3 >> s4); // $ ast,ir
sink(s1);
sink(s2); // $ ast,ir
sink(s3); // $ ast,ir
sink(s4); // $ ast MISSING: ir
sink(s4); // $ ast,ir
sink(ss1 >> b1);
sink(ss2 >> b2); // $ ast MISSING: ir
sink(ss2 >> b3 >> b4); // $ ast MISSING: ir
sink(ss2 >> b2); // $ ast,ir
sink(ss2 >> b3 >> b4); // $ ast,ir
sink(b1);
sink(b2); // $ ast,ir
sink(b3); // $ ast,ir
sink(b4); // $ ast MISSING: ir
sink(b4); // $ ast,ir
sink(ss1.read(b5, 100));
sink(ss2.read(b6, 100)); // $ ast MISSING: ir
sink(ss2.read(b6, 100)); // $ ast,ir
sink(ss1.readsome(b7, 100));
sink(ss2.readsome(b8, 100)); // (returns a length, not significantly tainted)
sink(ss1.get(b9, 100));
sink(ss2.get(b10, 100)); // $ ast MISSING: ir
sink(ss2.get(b10, 100)); // $ ast,ir
sink(b5);
sink(b6); // $ ast,ir
sink(b7);
@@ -176,7 +176,7 @@ void test_stringstream_in()
sink(c3 = ss1.peek());
sink(c4 = ss2.peek()); // $ ast,ir
sink(ss1.get(c5));
sink(ss2.get(c6)); // $ ast MISSING: ir
sink(ss2.get(c6)); // $ ast,ir
sink(c1);
sink(c2); // $ ast,ir
sink(c3);
@@ -212,44 +212,44 @@ void test_getline()
std::string s1, s2, s3, s4, s5, s6, s7, s8;
sink(ss1.getline(b1, 1000));
sink(ss2.getline(b2, 1000)); // $ ast MISSING: ir
sink(ss2.getline(b3, 1000)); // $ ast MISSING: ir
sink(ss2.getline(b2, 1000)); // $ ast,ir
sink(ss2.getline(b3, 1000)); // $ ast,ir
sink(ss1.getline(b3, 1000));
sink(b1);
sink(b2); // $ ast,ir
sink(b3); // $ SPURIOUS: ast,ir
sink(ss1.getline(b4, 1000, ' '));
sink(ss2.getline(b5, 1000, ' ')); // $ ast MISSING: ir
sink(ss2.getline(b6, 1000, ' ')); // $ ast MISSING: ir
sink(ss2.getline(b5, 1000, ' ')); // $ ast,ir
sink(ss2.getline(b6, 1000, ' ')); // $ ast,ir
sink(ss1.getline(b6, 1000, ' '));
sink(b4);
sink(b5); // $ ast,ir
sink(b6); // $ SPURIOUS: ast,ir
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast MISSING: ir
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast,ir
sink(b7); // $ ast,ir
sink(b8); // $ ast MISSING: ir
sink(getline(ss1, s1));
sink(getline(ss2, s2)); // $ ast MISSING: ir
sink(getline(ss2, s3)); // $ ast MISSING: ir
sink(getline(ss2, s2)); // $ ast,ir
sink(getline(ss2, s3)); // $ ast,ir
sink(getline(ss1, s3));
sink(s1);
sink(s2); // $ ast,ir
sink(s3); // $ SPURIOUS: ast,ir
sink(getline(ss1, s4, ' '));
sink(getline(ss2, s5, ' ')); // $ ast MISSING: ir
sink(getline(ss2, s6, ' ')); // $ ast MISSING: ir
sink(getline(ss2, s5, ' ')); // $ ast,ir
sink(getline(ss2, s6, ' ')); // $ ast,ir
sink(getline(ss1, s6, ' '));
sink(s4);
sink(s5); // $ ast,ir
sink(s6); // $ SPURIOUS: ast,ir
sink(getline(getline(ss2, s7), s8)); // $ ast MISSING: ir
sink(getline(getline(ss2, s7), s8)); // $ ast,ir
sink(s7); // $ ast,ir
sink(s8); // $ ast MISSING: ir
sink(s8); // $ ast,ir
}
void test_chaining()
@@ -259,7 +259,7 @@ void test_chaining()
char b1[1000] = {0};
char b2[1000] = {0};
sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast MISSING: ir
sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast,ir
sink(b1); // $ ast,ir
sink(b2); // $ ast MISSING: ir

View File

@@ -889,10 +889,8 @@ ssa.cpp:
# 207| m207_4(unknown) = Chi : total:m207_2, partial:m207_3
# 207| r207_5(glval<int>) = VariableAddress[x] :
# 207| m207_6(int) = InitializeParameter[x] : &:r207_5
# 207| m207_7(unknown) = Chi : total:m207_4, partial:m207_6
# 208| r208_1(glval<int>) = VariableAddress[y] :
# 208| m208_2(int) = Uninitialized[y] : &:r208_1
# 208| m208_3(unknown) = Chi : total:m207_7, partial:m208_2
# 209| r209_1(glval<unknown>) = FunctionAddress[memcpy] :
# 209| r209_2(glval<int>) = VariableAddress[y] :
# 209| r209_3(int *) = CopyValue : r209_2
@@ -904,15 +902,15 @@ ssa.cpp:
# 209| r209_9(void *) = Call[memcpy] : func:r209_1, 0:r209_4, 1:r209_7, 2:r209_8
# 209| v209_10(void) = ^SizedBufferReadSideEffect[1] : &:r209_7, r209_8, ~m207_6
# 209| m209_11(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r209_4, r209_8
# 209| m209_12(unknown) = Chi : total:m208_3, partial:m209_11
# 209| m209_12(int) = Chi : total:m208_2, partial:m209_11
# 210| r210_1(glval<int>) = VariableAddress[#return] :
# 210| r210_2(glval<int>) = VariableAddress[y] :
# 210| r210_3(int) = Load[y] : &:r210_2, ~m209_12
# 210| r210_3(int) = Load[y] : &:r210_2, m209_12
# 210| m210_4(int) = Store[#return] : &:r210_1, r210_3
# 207| r207_8(glval<int>) = VariableAddress[#return] :
# 207| v207_9(void) = ReturnValue : &:r207_8, m210_4
# 207| v207_10(void) = AliasedUse : m207_3
# 207| v207_11(void) = ExitFunction :
# 207| r207_7(glval<int>) = VariableAddress[#return] :
# 207| v207_8(void) = ReturnValue : &:r207_7, m210_4
# 207| v207_9(void) = AliasedUse : m207_3
# 207| v207_10(void) = ExitFunction :
# 213| void InitArray()
# 213| Block 0
@@ -1104,51 +1102,49 @@ ssa.cpp:
# 247| m247_6(char *) = InitializeParameter[src] : &:r247_5
# 247| r247_7(char *) = Load[src] : &:r247_5, m247_6
# 247| m247_8(unknown) = InitializeIndirection[src] : &:r247_7
# 247| m247_9(unknown) = Chi : total:m247_4, partial:m247_8
# 247| r247_10(glval<int>) = VariableAddress[size] :
# 247| m247_11(int) = InitializeParameter[size] : &:r247_10
# 247| r247_9(glval<int>) = VariableAddress[size] :
# 247| m247_10(int) = InitializeParameter[size] : &:r247_9
# 248| r248_1(glval<char *>) = VariableAddress[dst] :
# 248| r248_2(glval<unknown>) = FunctionAddress[operator new[]] :
# 248| r248_3(glval<int>) = VariableAddress[size] :
# 248| r248_4(int) = Load[size] : &:r248_3, m247_11
# 248| r248_4(int) = Load[size] : &:r248_3, m247_10
# 248| r248_5(unsigned long) = Convert : r248_4
# 248| r248_6(unsigned long) = Constant[1] :
# 248| r248_7(unsigned long) = Mul : r248_5, r248_6
# 248| r248_8(void *) = Call[operator new[]] : func:r248_2, 0:r248_7
# 248| m248_9(unknown) = ^CallSideEffect : ~m247_9
# 248| m248_10(unknown) = Chi : total:m247_9, partial:m248_9
# 248| m248_9(unknown) = ^CallSideEffect : ~m247_4
# 248| m248_10(unknown) = Chi : total:m247_4, partial:m248_9
# 248| m248_11(unknown) = ^InitializeDynamicAllocation : &:r248_8
# 248| m248_12(unknown) = Chi : total:m248_10, partial:m248_11
# 248| r248_13(char *) = Convert : r248_8
# 248| m248_14(char *) = Store[dst] : &:r248_1, r248_13
# 248| r248_12(char *) = Convert : r248_8
# 248| m248_13(char *) = Store[dst] : &:r248_1, r248_12
# 249| r249_1(char) = Constant[97] :
# 249| r249_2(glval<char *>) = VariableAddress[src] :
# 249| r249_3(char *) = Load[src] : &:r249_2, m247_6
# 249| r249_4(glval<char>) = CopyValue : r249_3
# 249| m249_5(char) = Store[?] : &:r249_4, r249_1
# 249| m249_6(unknown) = Chi : total:m248_12, partial:m249_5
# 249| m249_6(unknown) = Chi : total:m247_8, partial:m249_5
# 250| r250_1(glval<unknown>) = FunctionAddress[memcpy] :
# 250| r250_2(glval<char *>) = VariableAddress[dst] :
# 250| r250_3(char *) = Load[dst] : &:r250_2, m248_14
# 250| r250_3(char *) = Load[dst] : &:r250_2, m248_13
# 250| r250_4(void *) = Convert : r250_3
# 250| r250_5(glval<char *>) = VariableAddress[src] :
# 250| r250_6(char *) = Load[src] : &:r250_5, m247_6
# 250| r250_7(void *) = Convert : r250_6
# 250| r250_8(glval<int>) = VariableAddress[size] :
# 250| r250_9(int) = Load[size] : &:r250_8, m247_11
# 250| r250_9(int) = Load[size] : &:r250_8, m247_10
# 250| r250_10(void *) = Call[memcpy] : func:r250_1, 0:r250_4, 1:r250_7, 2:r250_9
# 250| v250_11(void) = ^SizedBufferReadSideEffect[1] : &:r250_7, r250_9, ~m249_6
# 250| m250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9
# 250| m250_13(unknown) = Chi : total:m249_6, partial:m250_12
# 250| m250_13(unknown) = Chi : total:m248_11, partial:m250_12
# 251| r251_1(glval<char *>) = VariableAddress[#return] :
# 251| r251_2(glval<char *>) = VariableAddress[dst] :
# 251| r251_3(char *) = Load[dst] : &:r251_2, m248_14
# 251| r251_3(char *) = Load[dst] : &:r251_2, m248_13
# 251| m251_4(char *) = Store[#return] : &:r251_1, r251_3
# 247| v247_12(void) = ReturnIndirection[src] : &:r247_7, ~m250_13
# 247| r247_13(glval<char *>) = VariableAddress[#return] :
# 247| v247_14(void) = ReturnValue : &:r247_13, m251_4
# 247| v247_15(void) = AliasedUse : ~m250_13
# 247| v247_16(void) = ExitFunction :
# 247| v247_11(void) = ReturnIndirection[src] : &:r247_7, m249_6
# 247| r247_12(glval<char *>) = VariableAddress[#return] :
# 247| v247_13(void) = ReturnValue : &:r247_12, m251_4
# 247| v247_14(void) = AliasedUse : ~m248_10
# 247| v247_15(void) = ExitFunction :
# 254| char StringLiteralAliasing2(bool)
# 254| Block 0
@@ -1206,39 +1202,37 @@ ssa.cpp:
# 268| m268_6(void *) = InitializeParameter[s] : &:r268_5
# 268| r268_7(void *) = Load[s] : &:r268_5, m268_6
# 268| m268_8(unknown) = InitializeIndirection[s] : &:r268_7
# 268| m268_9(unknown) = Chi : total:m268_4, partial:m268_8
# 268| r268_10(glval<int>) = VariableAddress[size] :
# 268| m268_11(int) = InitializeParameter[size] : &:r268_10
# 268| r268_9(glval<int>) = VariableAddress[size] :
# 268| m268_10(int) = InitializeParameter[size] : &:r268_9
# 269| r269_1(glval<void *>) = VariableAddress[buf] :
# 269| r269_2(glval<unknown>) = FunctionAddress[malloc] :
# 269| r269_3(glval<int>) = VariableAddress[size] :
# 269| r269_4(int) = Load[size] : &:r269_3, m268_11
# 269| r269_4(int) = Load[size] : &:r269_3, m268_10
# 269| r269_5(void *) = Call[malloc] : func:r269_2, 0:r269_4
# 269| m269_6(unknown) = ^CallSideEffect : ~m268_9
# 269| m269_7(unknown) = Chi : total:m268_9, partial:m269_6
# 269| m269_6(unknown) = ^CallSideEffect : ~m268_4
# 269| m269_7(unknown) = Chi : total:m268_4, partial:m269_6
# 269| m269_8(unknown) = ^InitializeDynamicAllocation : &:r269_5
# 269| m269_9(unknown) = Chi : total:m269_7, partial:m269_8
# 269| m269_10(void *) = Store[buf] : &:r269_1, r269_5
# 269| m269_9(void *) = Store[buf] : &:r269_1, r269_5
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
# 270| r270_3(void *) = Load[buf] : &:r270_2, m269_10
# 270| r270_3(void *) = Load[buf] : &:r270_2, m269_9
# 270| r270_4(glval<void *>) = VariableAddress[s] :
# 270| r270_5(void *) = Load[s] : &:r270_4, m268_6
# 270| r270_6(glval<int>) = VariableAddress[size] :
# 270| r270_7(int) = Load[size] : &:r270_6, m268_11
# 270| r270_7(int) = Load[size] : &:r270_6, m268_10
# 270| r270_8(void *) = Call[memcpy] : func:r270_1, 0:r270_3, 1:r270_5, 2:r270_7
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m269_7
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m268_8
# 270| m270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
# 270| m270_11(unknown) = Chi : total:m269_9, partial:m270_10
# 270| m270_11(unknown) = Chi : total:m269_8, partial:m270_10
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
# 271| r271_3(void *) = Load[buf] : &:r271_2, m269_10
# 271| r271_3(void *) = Load[buf] : &:r271_2, m269_9
# 271| m271_4(void *) = Store[#return] : &:r271_1, r271_3
# 268| v268_12(void) = ReturnIndirection[s] : &:r268_7, ~m270_11
# 268| r268_13(glval<void *>) = VariableAddress[#return] :
# 268| v268_14(void) = ReturnValue : &:r268_13, m271_4
# 268| v268_15(void) = AliasedUse : ~m270_11
# 268| v268_16(void) = ExitFunction :
# 268| v268_11(void) = ReturnIndirection[s] : &:r268_7, m268_8
# 268| r268_12(glval<void *>) = VariableAddress[#return] :
# 268| v268_13(void) = ReturnValue : &:r268_12, m271_4
# 268| v268_14(void) = AliasedUse : ~m269_7
# 268| v268_15(void) = ExitFunction :
# 275| void EscapedButNotConflated(bool, Point, int)
# 275| Block 0

View File

@@ -1464,117 +1464,93 @@ unreachableNodeCCtx
localCallNodes
postIsNotPre
postHasUniquePre
| assignexpr.cpp:9:2:9:12 | Store | PostUpdateNode should have one pre-update node but has 0. |
| bad_asts.cpp:15:10:15:12 | Store | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:65:19:65:45 | Store | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:531:14:531:14 | Store | PostUpdateNode should have one pre-update node but has 0. |
| allocators.cpp:16:14:16:36 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. |
| condition_decls.cpp:16:19:16:20 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. |
| condition_decls.cpp:26:23:26:24 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. |
| condition_decls.cpp:41:22:41:23 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. |
| condition_decls.cpp:48:22:48:24 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. |
| condition_decls.cpp:48:34:48:36 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. |
| condition_decls.cpp:48:52:48:53 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. |
| conditional_destructors.cpp:30:9:30:13 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| conditional_destructors.cpp:30:18:30:22 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| conditional_destructors.cpp:33:9:33:13 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| conditional_destructors.cpp:33:18:33:22 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| conditional_destructors.cpp:39:9:39:13 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| conditional_destructors.cpp:39:18:39:22 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| conditional_destructors.cpp:42:9:42:13 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| conditional_destructors.cpp:42:18:42:22 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| constructorinitializer.cpp:8:6:8:18 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:77:19:77:21 | Val output argument | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:82:11:82:14 | Val output argument | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:82:17:82:55 | Val output argument | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:82:45:82:48 | Val output argument | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:82:51:82:51 | Val output argument | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:88:25:88:30 | Val output argument | PostUpdateNode should have one pre-update node but has 0. |
| cpp11.cpp:88:33:88:38 | Val output argument | PostUpdateNode should have one pre-update node but has 0. |
| cpp17.cpp:15:5:15:45 | HasTwoArgCtor output argument | PostUpdateNode should have one pre-update node but has 0. |
| destructors.cpp:50:9:50:13 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| destructors.cpp:51:36:51:38 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| file://:0:0:0:0 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:616:12:616:13 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:617:15:617:22 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:619:16:619:30 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:662:9:662:19 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:663:5:663:5 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:736:5:736:19 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:745:8:745:8 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:748:10:748:10 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:757:12:757:12 | Base output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:757:12:757:12 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:766:13:766:13 | Middle output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:766:13:766:13 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:775:15:775:15 | Base output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:775:15:775:15 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:784:15:784:15 | Base output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:784:15:784:15 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:793:15:793:15 | Base output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:793:15:793:15 | MiddleVB1 output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:793:15:793:15 | MiddleVB2 output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:793:15:793:15 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:800:8:800:8 | Base output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:801:10:801:10 | Middle output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:802:11:802:11 | Derived output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:809:7:809:13 | Base output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:810:7:810:26 | Base output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:823:7:823:13 | Base output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:824:7:824:26 | Base output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:846:8:846:8 | PolymorphicBase output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:850:19:850:19 | PolymorphicBase output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:851:22:851:22 | PolymorphicDerived output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:868:3:868:12 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:944:3:944:14 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ir.cpp:945:3:945:27 | String output argument | PostUpdateNode should have one pre-update node but has 0. |
| ms_assume.cpp:28:18:28:23 | fgets output argument | PostUpdateNode should have one pre-update node but has 0. |
| ms_try_mix.cpp:11:12:11:15 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| ms_try_mix.cpp:28:12:28:15 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| ms_try_mix.cpp:48:10:48:13 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| newexpr.cpp:8:2:8:20 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| ops.cpp:26:31:26:53 | C_with_constr_destr output argument | PostUpdateNode should have one pre-update node but has 0. |
| parameterinitializer.cpp:25:5:25:8 | c output argument | PostUpdateNode should have one pre-update node but has 0. |
| static_init_templates.cpp:31:10:31:11 | MyClass output argument | PostUpdateNode should have one pre-update node but has 0. |
| static_init_templates.cpp:236:7:236:7 | MyConstructorClass output argument | PostUpdateNode should have one pre-update node but has 0. |
| static_init_templates.cpp:240:7:240:7 | MyConstructorClass output argument | PostUpdateNode should have one pre-update node but has 0. |
| static_init_templates.cpp:249:21:249:23 | MyConstructorClass output argument | PostUpdateNode should have one pre-update node but has 0. |
| static_init_templates.cpp:250:17:250:19 | MyDerivedClass output argument | PostUpdateNode should have one pre-update node but has 0. |
| static_init_templates.cpp:251:20:251:23 | MyContainingClass output argument | PostUpdateNode should have one pre-update node but has 0. |
| stmt_expr.cpp:13:18:13:19 | C output argument | PostUpdateNode should have one pre-update node but has 0. |
| try_catch.cpp:7:8:7:8 | exception output argument | PostUpdateNode should have one pre-update node but has 0. |
| try_catch.cpp:7:8:7:8 | exception output argument | PostUpdateNode should have one pre-update node but has 0. |
| try_catch.cpp:13:5:13:16 | exn1 output argument | PostUpdateNode should have one pre-update node but has 0. |
uniquePostUpdate
postIsInSameCallable
reverseRead
argHasPostUpdate
postWithInFlow
| aggregateinitializer.c:3:14:3:18 | Chi | PostUpdateNode should not be the target of local flow. |
| aggregateinitializer.c:3:21:3:25 | Chi | PostUpdateNode should not be the target of local flow. |
| allocators.cpp:3:27:3:27 | Chi | PostUpdateNode should not be the target of local flow. |
| allocators.cpp:3:35:3:35 | Chi | PostUpdateNode should not be the target of local flow. |
| allocators.cpp:4:11:4:23 | Chi | PostUpdateNode should not be the target of local flow. |
| allocators.cpp:4:17:4:23 | Chi | PostUpdateNode should not be the target of local flow. |
| assignexpr.cpp:9:2:9:12 | Store | PostUpdateNode should not be the target of local flow. |
| bad_asts.cpp:15:10:15:12 | Store | PostUpdateNode should not be the target of local flow. |
| builtin.c:14:26:14:26 | Chi | PostUpdateNode should not be the target of local flow. |
| builtin.c:14:29:14:29 | Chi | PostUpdateNode should not be the target of local flow. |
| builtin.c:14:32:14:32 | Chi | PostUpdateNode should not be the target of local flow. |
| builtin.c:14:35:14:35 | Chi | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:3:5:3:22 | Chi | PostUpdateNode should not be the target of local flow. |
| condition_decls.cpp:3:21:3:21 | Chi | PostUpdateNode should not be the target of local flow. |
| conditional_destructors.cpp:6:13:6:19 | Chi | PostUpdateNode should not be the target of local flow. |
| conditional_destructors.cpp:18:13:18:19 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:65:19:65:45 | Store | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:17:82:55 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:17:82:55 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:45:82:48 | Chi | PostUpdateNode should not be the target of local flow. |
| defdestructordeleteexpr.cpp:4:9:4:15 | Chi | PostUpdateNode should not be the target of local flow. |
| deleteexpr.cpp:7:9:7:15 | Chi | PostUpdateNode should not be the target of local flow. |
| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. |
| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. |
| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:177:5:177:12 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:178:5:178:12 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:183:5:183:12 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:184:5:184:12 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:342:5:342:10 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:428:5:428:12 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:429:5:429:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:504:19:504:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:504:22:504:22 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:505:16:505:21 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:505:19:505:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:506:16:506:18 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:506:16:506:18 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:513:14:513:16 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:513:14:513:16 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:514:14:514:26 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:514:19:514:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:514:22:514:22 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:515:19:515:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:515:22:515:22 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:515:29:515:29 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:515:32:515:32 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:516:17:516:21 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:516:19:516:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:516:24:516:28 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:516:26:516:26 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:521:19:521:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:521:22:521:22 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:521:25:521:25 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:522:16:522:21 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:522:19:522:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:531:14:531:14 | Store | PostUpdateNode should not be the target of local flow. |
| ir.cpp:577:16:577:21 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:577:19:577:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:578:19:578:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:578:22:578:22 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:579:16:579:21 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:579:19:579:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:643:9:643:21 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:644:9:644:23 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:645:9:645:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:659:9:659:14 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:660:13:660:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:661:9:661:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:662:9:662:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:663:5:663:5 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:745:8:745:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:745:8:745:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:748:10:748:10 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:754:8:754:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:757:12:757:12 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:763:8:763:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:766:13:766:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:775:15:775:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:784:15:784:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:793:15:793:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:943:3:943:11 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:947:3:947:25 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:962:17:962:47 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:962:17:962:47 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:962:17:962:47 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:962:26:962:30 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:962:41:962:45 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:130:5:130:11 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:131:5:131:13 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:154:32:154:32 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:154:35:154:35 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:154:40:154:40 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:154:43:154:43 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:157:14:157:18 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:158:14:158:18 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:160:31:160:33 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:160:31:160:33 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:220:3:223:3 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:221:10:221:10 | Chi | PostUpdateNode should not be the target of local flow. |
| misc.c:222:10:222:10 | Chi | PostUpdateNode should not be the target of local flow. |
| range_analysis.c:102:5:102:15 | Chi | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:3:2:3:8 | Chi | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:21:2:21:12 | Chi | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:240:7:240:7 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:77:19:77:21 | Val output argument | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:11:82:14 | Val output argument | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:45:82:48 | Val output argument | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:51:82:51 | Val output argument | PostUpdateNode should not be the target of local flow. |
| ir.cpp:809:7:809:13 | Base output argument | PostUpdateNode should not be the target of local flow. |
| ir.cpp:810:7:810:26 | Base output argument | PostUpdateNode should not be the target of local flow. |
| ir.cpp:823:7:823:13 | Base output argument | PostUpdateNode should not be the target of local flow. |
| ir.cpp:824:7:824:26 | Base output argument | PostUpdateNode should not be the target of local flow. |

View File

@@ -2,3 +2,4 @@ name: codeql-cpp-tests
version: 0.0.0
libraryPathDependencies: codeql-cpp
extractor: cpp
tests: .

View File

@@ -0,0 +1,13 @@
edges
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | (const char *)... |
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | (const char *)... |
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 |
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 |
nodes
| test.c:15:20:15:23 | argv | semmle.label | argv |
| test.c:15:20:15:23 | argv | semmle.label | argv |
| test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... |
| test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... |
| test.c:21:18:21:23 | query1 | semmle.label | query1 |
#select
| test.c:21:18:21:23 | query1 | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg) | test.c:15:20:15:23 | argv | user input (argv) |

View File

@@ -0,0 +1 @@
Security/CWE/CWE-089/SqlTainted.ql

View File

@@ -0,0 +1,34 @@
// Semmle test case for rule SprintfToSqlQuery.ql (Uncontrolled sprintf for SQL query)
// Associated with CWE-089: SQL injection. http://cwe.mitre.org/data/definitions/89.html
///// Library routines /////
typedef unsigned long size_t;
int snprintf(char *s, size_t n, const char *format, ...);
void sanitizeString(char *stringOut, size_t len, const char *strIn);
int mysql_query(int arg1, const char *sqlArg);
int atoi(const char *nptr);
///// Test code /////
int main(int argc, char** argv) {
char *userName = argv[2];
int userNumber = atoi(argv[3]);
// a string from the user is injected directly into an SQL query.
char query1[1000] = {0};
snprintf(query1, 1000, "SELECT UID FROM USERS where name = \"%s\"", userName);
mysql_query(0, query1); // BAD
// the user string is encoded by a library routine.
char userNameSanitized[1000] = {0};
sanitizeString(userNameSanitized, 1000, userName);
char query2[1000] = {0};
snprintf(query2, 1000, "SELECT UID FROM USERS where name = \"%s\"", userNameSanitized);
mysql_query(0, query2); // GOOD
// an integer from the user is injected into an SQL query.
char query3[1000] = {0};
snprintf(query3, 1000, "SELECT UID FROM USERS where number = \"%i\"", userNumber);
mysql_query(0, query3); // GOOD
}

View File

@@ -59,18 +59,21 @@ edges
| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size |
| test.cpp:241:2:241:32 | Chi [array content] | test.cpp:279:17:279:20 | get_size output argument [array content] |
| test.cpp:241:2:241:32 | Chi [array content] | test.cpp:295:18:295:21 | get_size output argument [array content] |
| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | Chi [array content] |
| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | Chi [array content] |
| test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | test.cpp:241:2:241:32 | Chi [array content] |
| test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | test.cpp:279:17:279:20 | get_size output argument [array content] |
| test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | test.cpp:295:18:295:21 | get_size output argument [array content] |
| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | ChiTotal [post update] [array content] |
| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | ChiTotal [post update] [array content] |
| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:279:17:279:20 | Chi | test.cpp:281:11:281:28 | ... * ... |
| test.cpp:279:17:279:20 | Chi | test.cpp:281:11:281:28 | ... * ... |
| test.cpp:279:17:279:20 | get_size output argument [array content] | test.cpp:279:17:279:20 | Chi |
| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | get_size output argument [array content] | test.cpp:295:18:295:21 | Chi |
| test.cpp:279:17:279:20 | get_size output argument | test.cpp:281:11:281:28 | ... * ... |
| test.cpp:279:17:279:20 | get_size output argument | test.cpp:281:11:281:28 | ... * ... |
| test.cpp:279:17:279:20 | get_size output argument [array content] | test.cpp:279:17:279:20 | get_size output argument |
| test.cpp:295:18:295:21 | get_size output argument | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | get_size output argument | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | get_size output argument [array content] | test.cpp:295:18:295:21 | get_size output argument |
| test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... |
| test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... |
| test.cpp:301:19:301:32 | (const char *)... | test.cpp:305:11:305:28 | ... * ... |
@@ -144,6 +147,7 @@ nodes
| test.cpp:237:2:237:8 | Argument 0 | semmle.label | Argument 0 |
| test.cpp:241:2:241:32 | Chi [array content] | semmle.label | Chi [array content] |
| test.cpp:241:2:241:32 | ChiPartial | semmle.label | ChiPartial |
| test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] |
| test.cpp:241:18:241:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:241:18:241:31 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:249:20:249:25 | call to getenv | semmle.label | call to getenv |
@@ -151,12 +155,12 @@ nodes
| test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... |
| test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... |
| test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... |
| test.cpp:279:17:279:20 | Chi | semmle.label | Chi |
| test.cpp:279:17:279:20 | get_size output argument | semmle.label | get_size output argument |
| test.cpp:279:17:279:20 | get_size output argument [array content] | semmle.label | get_size output argument [array content] |
| test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:295:18:295:21 | Chi | semmle.label | Chi |
| test.cpp:295:18:295:21 | get_size output argument | semmle.label | get_size output argument |
| test.cpp:295:18:295:21 | get_size output argument [array content] | semmle.label | get_size output argument [array content] |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |

View File

@@ -43,19 +43,23 @@ edges
| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store |
| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store |
| test.cpp:13:2:13:15 | Chi [array content] | test.cpp:30:13:30:14 | get_rand2 output argument [array content] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [array content] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [array content] |
| test.cpp:13:2:13:15 | ChiTotal [post update] [array content] | test.cpp:13:2:13:15 | Chi [array content] |
| test.cpp:13:2:13:15 | ChiTotal [post update] [array content] | test.cpp:30:13:30:14 | get_rand2 output argument [array content] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | ChiTotal [post update] [array content] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | ChiTotal [post update] [array content] |
| test.cpp:18:2:18:14 | Chi [array content] | test.cpp:36:13:36:13 | get_rand3 output argument [array content] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [array content] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [array content] |
| test.cpp:18:2:18:14 | ChiTotal [post update] [array content] | test.cpp:18:2:18:14 | Chi [array content] |
| test.cpp:18:2:18:14 | ChiTotal [post update] [array content] | test.cpp:36:13:36:13 | get_rand3 output argument [array content] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | ChiTotal [post update] [array content] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | ChiTotal [post update] [array content] |
| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r |
| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r |
| test.cpp:30:13:30:14 | Chi | test.cpp:31:7:31:7 | r |
| test.cpp:30:13:30:14 | Chi | test.cpp:31:7:31:7 | r |
| test.cpp:30:13:30:14 | get_rand2 output argument [array content] | test.cpp:30:13:30:14 | Chi |
| test.cpp:36:13:36:13 | Chi | test.cpp:37:7:37:7 | r |
| test.cpp:36:13:36:13 | Chi | test.cpp:37:7:37:7 | r |
| test.cpp:36:13:36:13 | get_rand3 output argument [array content] | test.cpp:36:13:36:13 | Chi |
| test.cpp:30:13:30:14 | get_rand2 output argument | test.cpp:31:7:31:7 | r |
| test.cpp:30:13:30:14 | get_rand2 output argument | test.cpp:31:7:31:7 | r |
| test.cpp:30:13:30:14 | get_rand2 output argument [array content] | test.cpp:30:13:30:14 | get_rand2 output argument |
| test.cpp:36:13:36:13 | get_rand3 output argument | test.cpp:37:7:37:7 | r |
| test.cpp:36:13:36:13 | get_rand3 output argument | test.cpp:37:7:37:7 | r |
| test.cpp:36:13:36:13 | get_rand3 output argument [array content] | test.cpp:36:13:36:13 | get_rand3 output argument |
nodes
| test.c:18:13:18:16 | call to rand | semmle.label | call to rand |
| test.c:18:13:18:16 | call to rand | semmle.label | call to rand |
@@ -110,22 +114,24 @@ nodes
| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand |
| test.cpp:13:2:13:15 | Chi [array content] | semmle.label | Chi [array content] |
| test.cpp:13:2:13:15 | ChiPartial | semmle.label | ChiPartial |
| test.cpp:13:2:13:15 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] |
| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand |
| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand |
| test.cpp:18:2:18:14 | Chi [array content] | semmle.label | Chi [array content] |
| test.cpp:18:2:18:14 | ChiPartial | semmle.label | ChiPartial |
| test.cpp:18:2:18:14 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] |
| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand |
| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand |
| test.cpp:24:11:24:18 | call to get_rand | semmle.label | call to get_rand |
| test.cpp:25:7:25:7 | r | semmle.label | r |
| test.cpp:25:7:25:7 | r | semmle.label | r |
| test.cpp:25:7:25:7 | r | semmle.label | r |
| test.cpp:30:13:30:14 | Chi | semmle.label | Chi |
| test.cpp:30:13:30:14 | get_rand2 output argument | semmle.label | get_rand2 output argument |
| test.cpp:30:13:30:14 | get_rand2 output argument [array content] | semmle.label | get_rand2 output argument [array content] |
| test.cpp:31:7:31:7 | r | semmle.label | r |
| test.cpp:31:7:31:7 | r | semmle.label | r |
| test.cpp:31:7:31:7 | r | semmle.label | r |
| test.cpp:36:13:36:13 | Chi | semmle.label | Chi |
| test.cpp:36:13:36:13 | get_rand3 output argument | semmle.label | get_rand3 output argument |
| test.cpp:36:13:36:13 | get_rand3 output argument [array content] | semmle.label | get_rand3 output argument [array content] |
| test.cpp:37:7:37:7 | r | semmle.label | r |
| test.cpp:37:7:37:7 | r | semmle.label | r |

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* The `UnaryPatternExpr` and `NotPatternExpr` classes have been added to support
C# 9 unary `not` pattern.

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* The `RelationalPatternExpr` and its 4 sub class have been added to support C# 9
relational `<`, `>`, `<=`, and `>=` patterns.

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* Function pointer types (`FunctionPointerType`) and call to function pointers
(`FunctionPointerCall`) are extracted.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Function pointer types (`FunctionPointerType`) are extracted from IL. Also, `pinned` and `by-reference` (`cil_type_annotation`) type extraction is fixed.

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Types that are passed by reference are not written directly to trap files. Instead, the annotation is stored on
/// the entity.
/// </summary>
internal sealed class ByRefType : Type
{
public ByRefType(Context cx, Type elementType) : base(cx)
{
ElementType = elementType;
}
public override CilTypeKind Kind => throw new NotImplementedException();
public override Namespace? ContainingNamespace => throw new NotImplementedException();
public override Type? ContainingType => throw new NotImplementedException();
public override int ThisTypeParameterCount => throw new NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
public override string Name => $"{ElementType.Name}&";
public Type ElementType { get; }
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(TextWriter trapFile, bool inContext)
{
ElementType.WriteId(trapFile, inContext);
trapFile.Write('&');
}
}
}

View File

@@ -8,6 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
ValueOrRefType,
TypeParameter,
Array,
Pointer
Pointer,
FunctionPointer
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
@@ -36,12 +37,26 @@ namespace Semmle.Extraction.CIL.Entities
}
var name = type.GetQualifiedName();
if (wellKnownEnums.TryGetValue(name, out var code))
{
cx.Cx.Extractor.Logger.Log(Util.Logging.Severity.Debug, $"Using hard coded underlying enum type for {name}");
return code;
}
cx.Cx.Extractor.Logger.Log(Util.Logging.Severity.Info, $"Couldn't get underlying enum type for {name}");
// We can't fall back to Int32, because the type returned here defines how many bytes are read from the
// stream and how those bytes are interpreted.
throw new NotImplementedException();
}
public bool IsSystemType(Type type) => type.GetQualifiedName() == "System.Type";
private static readonly Dictionary<string, PrimitiveTypeCode> wellKnownEnums = new Dictionary<string, PrimitiveTypeCode>
{
{ "System.AttributeTargets", PrimitiveTypeCode.Int32 },
{ "System.ComponentModel.EditorBrowsableState", PrimitiveTypeCode.Int32 }
};
}
}

View File

@@ -121,8 +121,19 @@ namespace Semmle.Extraction.CIL.Entities
for (var l = 0; l < this.locals.Length; ++l)
{
this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, localVariableTypes[l]));
yield return this.locals[l];
var t = localVariableTypes[l];
if (t is ByRefType brt)
{
t = brt.ElementType;
this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, t));
yield return this.locals[l];
yield return Tuples.cil_type_annotation(this.locals[l], TypeAnnotation.Ref);
}
else
{
this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, t));
yield return this.locals[l];
}
}
}

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class FunctionPointerType : Type, IParameterizable, ICustomModifierReceiver
{
private readonly MethodSignature<Type> signature;
public FunctionPointerType(Context cx, MethodSignature<Type> signature) : base(cx)
{
this.signature = signature;
}
public override CilTypeKind Kind => CilTypeKind.FunctionPointer;
public override string Name
{
get
{
using var id = new StringWriter();
WriteName(
id.Write,
t => id.Write(t.Name),
signature
);
return id.ToString();
}
}
public override Namespace? ContainingNamespace => Cx.GlobalNamespace;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => throw new System.NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new System.NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new System.NotImplementedException();
public override void WriteAssemblyPrefix(TextWriter trapFile) { }
public override void WriteId(TextWriter trapFile, bool inContext)
{
WriteName(
trapFile.Write,
t => t.WriteId(trapFile, inContext),
signature
);
}
internal static void WriteName<TType>(Action<string> write, Action<TType> writeType, MethodSignature<TType> signature)
{
write("delegate* ");
write(GetCallingConvention(signature.Header.CallingConvention));
write("<");
foreach (var pt in signature.ParameterTypes)
{
writeType(pt);
write(",");
}
writeType(signature.ReturnType);
write(">");
}
internal static string GetCallingConvention(SignatureCallingConvention callingConvention)
{
if (callingConvention == SignatureCallingConvention.Default)
{
return "managed";
}
if (callingConvention == SignatureCallingConvention.Unmanaged)
{
return "unmanaged";
}
return $"unmanaged[{callingConvention}]";
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
{
yield return c;
}
var retType = signature.ReturnType;
if (retType is ModifiedType mt)
{
retType = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (retType is ByRefType byRefType)
{
retType = byRefType.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_function_pointer_return_type(this, retType);
yield return Tuples.cil_function_pointer_calling_conventions(this, signature.Header.CallingConvention);
foreach (var p in Method.GetParameterExtractionProducts(signature.ParameterTypes, this, this, Cx, 0))
{
yield return p;
}
}
}
}
}

View File

@@ -0,0 +1,7 @@
namespace Semmle.Extraction.CIL.Entities
{
internal interface IParameterizable : IEntity
{
}
}

View File

@@ -9,7 +9,7 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary>
/// A method entity.
/// </summary>
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver, IParameterizable
{
protected MethodTypeParameter[]? genericParams;
protected GenericContext gc;
@@ -86,15 +86,34 @@ namespace Semmle.Extraction.CIL.Entities
yield return Cx.Populate(new Parameter(Cx, this, i++, DeclaringType));
}
foreach (var p in GetParameterExtractionProducts(parameterTypes, this, this, Cx, i))
{
yield return p;
}
}
internal static IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes, IParameterizable parameterizable, ICustomModifierReceiver receiver, Context cx, int firstChildIndex)
{
var i = firstChildIndex;
foreach (var p in parameterTypes)
{
var t = p;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
yield return Tuples.cil_custom_modifiers(receiver, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
var parameter = cx.Populate(new Parameter(cx, parameterizable, i++, t));
yield return parameter;
yield return Tuples.cil_type_annotation(parameter, TypeAnnotation.Ref);
}
else
{
yield return cx.Populate(new Parameter(cx, parameterizable, i++, t));
}
yield return Cx.Populate(new Parameter(Cx, this, i++, t));
}
}
@@ -106,6 +125,11 @@ namespace Semmle.Extraction.CIL.Entities
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_method(this, name, declaringType, t);
}
}

View File

@@ -37,6 +37,13 @@ namespace Semmle.Extraction.CIL.Entities
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(TextWriter trapFile, bool inContext) => throw new NotImplementedException();
public override void WriteId(TextWriter trapFile, bool inContext)
{
Unmodified.WriteId(trapFile, inContext);
trapFile.Write(IsRequired ? " modreq" : " modopt");
trapFile.Write("(");
Modifier.WriteId(trapFile, inContext);
trapFile.Write(")");
}
}
}

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities
{
@@ -21,6 +20,7 @@ namespace Semmle.Extraction.CIL.Entities
private readonly Type[]? thisTypeArguments;
private readonly Type unboundGenericType;
private readonly Type? containingType;
private readonly Namespace? containingNamespace;
private readonly NamedTypeIdWriter idWriter;
@@ -53,13 +53,20 @@ namespace Semmle.Extraction.CIL.Entities
? null
: new NoMetadataHandleType(Cx, containerName);
containingNamespace = isContainerNamespace
? containerName == Cx.GlobalNamespace.Name
? Cx.GlobalNamespace
: containerName == Cx.SystemNamespace.Name
? Cx.SystemNamespace
: new Namespace(Cx, containerName)
: null;
Populate();
}
private void Populate()
{
if (isContainerNamespace &&
!ContainingNamespace!.IsGlobalNamespace)
if (isContainerNamespace)
{
Cx.Populate(ContainingNamespace);
}
@@ -100,11 +107,7 @@ namespace Semmle.Extraction.CIL.Entities
public override string Name => GenericsHelper.GetNonGenericName(name);
public override Namespace? ContainingNamespace => isContainerNamespace
? containerName == Cx.GlobalNamespace.Name
? Cx.GlobalNamespace
: new Namespace(Cx, containerName)
: null;
public override Namespace? ContainingNamespace => containingNamespace;
public override Type? ContainingType => containingType;

View File

@@ -8,11 +8,11 @@ namespace Semmle.Extraction.CIL.Entities
/// </summary>
internal sealed class Parameter : LabelledEntity
{
private readonly Method method;
private readonly IParameterizable method;
private readonly int index;
private readonly Type type;
public Parameter(Context cx, Method m, int i, Type t) : base(cx)
public Parameter(Context cx, IParameterizable m, int i, Type t) : base(cx)
{
method = m;
index = i;

View File

@@ -62,6 +62,11 @@ namespace Semmle.Extraction.CIL.Entities
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_property(this, type, name, t);
var accessors = pd.GetAccessors();

View File

@@ -41,17 +41,27 @@ namespace Semmle.Extraction.CIL.Entities
public void WriteId(TextWriter trapFile, GenericContext gc)
{
trapFile.Write("ref ");
elementType.WriteId(trapFile, gc);
trapFile.Write('&');
}
}
private struct FnPtr : ITypeSignature
{
private readonly MethodSignature<ITypeSignature> signature;
public FnPtr(MethodSignature<ITypeSignature> signature)
{
this.signature = signature;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
trapFile.Write("<method signature>");
FunctionPointerType.WriteName(
trapFile.Write,
t => t.WriteId(trapFile, gc),
signature
);
}
}
@@ -62,7 +72,7 @@ namespace Semmle.Extraction.CIL.Entities
new ByRef(elementType);
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetFunctionPointerType(MethodSignature<ITypeSignature> signature) =>
new FnPtr();
new FnPtr(signature);
private class Instantiation : ITypeSignature
{
@@ -163,25 +173,9 @@ namespace Semmle.Extraction.CIL.Entities
return new Modified(unmodifiedType, modifier, isRequired);
}
private class Pinned : ITypeSignature
{
private readonly ITypeSignature elementType;
public Pinned(ITypeSignature elementType)
{
this.elementType = elementType;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
trapFile.Write("pinned ");
elementType.WriteId(trapFile, gc);
}
}
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetPinnedType(ITypeSignature elementType)
{
return new Pinned(elementType);
return elementType;
}
private class PointerType : ITypeSignature

View File

@@ -0,0 +1,11 @@
using System;
namespace Semmle.Extraction.CIL.Entities
{
[Flags]
public enum TypeAnnotation
{
None = 0,
Ref = 32
}
}

View File

@@ -20,10 +20,10 @@ namespace Semmle.Extraction.CIL.Entities
cx.Populate(new ArrayType(cx, elementType, shape.Rank));
Type IConstructedTypeProvider<Type>.GetByReferenceType(Type elementType) =>
elementType; // ??
new ByRefType(cx, elementType);
Type ISignatureTypeProvider<Type, GenericContext>.GetFunctionPointerType(MethodSignature<Type> signature) =>
cx.ErrorType; // Don't know what to do !!
cx.Populate(new FunctionPointerType(cx, signature));
Type IConstructedTypeProvider<Type>.GetGenericInstantiation(Type genericType, ImmutableArray<Type> typeArguments) =>
genericType.Construct(typeArguments);
@@ -37,8 +37,7 @@ namespace Semmle.Extraction.CIL.Entities
Type ISignatureTypeProvider<Type, GenericContext>.GetModifiedType(Type modifier, Type unmodifiedType, bool isRequired) =>
new ModifiedType(cx, unmodifiedType, modifier, isRequired);
Type ISignatureTypeProvider<Type, GenericContext>.GetPinnedType(Type elementType) =>
cx.Populate(new PointerType(cx, elementType));
Type ISignatureTypeProvider<Type, GenericContext>.GetPinnedType(Type elementType) => elementType;
Type IConstructedTypeProvider<Type>.GetPointerType(Type elementType) =>
cx.Populate(new PointerType(cx, elementType));

View File

@@ -86,6 +86,12 @@ namespace Semmle.Extraction.CIL
internal static Tuple cil_method(Method method, string name, Type declType, Type returnType) =>
new Tuple("cil_method", method, name, declType, returnType);
internal static Tuple cil_function_pointer_return_type(FunctionPointerType fnptr, Type returnType) =>
new Tuple("cil_function_pointer_return_type", fnptr, returnType);
internal static Tuple cil_function_pointer_calling_conventions(FunctionPointerType fnptr, System.Reflection.Metadata.SignatureCallingConvention callingConvention) =>
new Tuple("cil_function_pointer_calling_conventions", fnptr, (int)callingConvention);
internal static Tuple cil_method_implementation(MethodImplementation impl, Method method, Assembly assembly) =>
new Tuple("cil_method_implementation", impl, method, assembly);
@@ -101,7 +107,7 @@ namespace Semmle.Extraction.CIL
internal static Tuple cil_newslot(Method method) =>
new Tuple("cil_newslot", method);
internal static Tuple cil_parameter(Parameter p, Method m, int i, Type t) =>
internal static Tuple cil_parameter(Parameter p, IParameterizable m, int i, Type t) =>
new Tuple("cil_parameter", p, m, i, t);
internal static Tuple cil_parameter_in(Parameter p) =>
@@ -191,6 +197,9 @@ namespace Semmle.Extraction.CIL
internal static Tuple cil_custom_modifiers(ICustomModifierReceiver receiver, Type modifier, bool isRequired) =>
new Tuple("cil_custom_modifiers", receiver, modifier, isRequired ? 1 : 0);
internal static Tuple cil_type_annotation(IEntity receiver, TypeAnnotation annotation) =>
new Tuple("cil_type_annotation", receiver, (int)annotation);
internal static Tuple containerparent(Folder parent, IFileOrFolder child) =>
new Tuple("containerparent", parent, child);

View File

@@ -232,7 +232,7 @@ namespace Semmle.Extraction.CSharp
var projectLayout = layout.LookupProjectOrDefault(transformedAssemblyPath);
var trapWriter = projectLayout.CreateTrapWriter(Logger, transformedAssemblyPath, options.TrapCompression, discardDuplicates: false);
compilationTrapFile = trapWriter; // Dispose later
var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath, true), AddAssemblyTrapPrefix);
var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath), AddAssemblyTrapPrefix);
compilationEntity = new Entities.Compilation(cx, cwd, args);
}
@@ -287,7 +287,7 @@ namespace Semmle.Extraction.CSharp
if (c.GetAssemblyOrModuleSymbol(r) is IAssemblySymbol assembly)
{
var cx = extractor.CreateContext(c, trapWriter, new AssemblyScope(assembly, assemblyPath, false), AddAssemblyTrapPrefix);
var cx = extractor.CreateContext(c, trapWriter, new AssemblyScope(assembly, assemblyPath), AddAssemblyTrapPrefix);
foreach (var module in assembly.Modules)
{

View File

@@ -21,9 +21,10 @@ namespace Semmle.Extraction.CSharp.Entities
protected override void Populate(TextWriter trapFile)
{
Extraction.Entities.Assembly.CreateOutputAssembly(cx);
var assembly = Extraction.Entities.Assembly.CreateOutputAssembly(cx);
trapFile.compilations(this, FileUtils.ConvertToUnix(cwd));
trapFile.compilation_assembly(this, assembly);
// Arguments
var index = 0;

View File

@@ -42,16 +42,16 @@ namespace Semmle.Extraction.CSharp.Entities
if (initializer == null)
return;
Type initializerType;
ITypeSymbol initializerType;
var symbolInfo = Context.GetSymbolInfo(initializer);
switch (initializer.Kind())
{
case SyntaxKind.BaseConstructorInitializer:
initializerType = Type.Create(Context, symbol.ContainingType.BaseType);
initializerType = symbol.ContainingType.BaseType;
break;
case SyntaxKind.ThisConstructorInitializer:
initializerType = ContainingType;
initializerType = symbol.ContainingType;
break;
default:
Context.ModelError(initializer, "Unknown initializer");
@@ -59,7 +59,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
var initInfo = new ExpressionInfo(Context,
new AnnotatedType(initializerType, NullableAnnotation.None),
AnnotatedTypeSymbol.CreateNotAnnotated(initializerType),
Context.Create(initializer.ThisOrBaseKeyword.GetLocation()),
Kinds.ExprKind.CONSTRUCTOR_INIT,
this,

View File

@@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities
internal class Expression : FreshEntity, IExpressionParentEntity
{
private readonly IExpressionInfo info;
public AnnotatedType Type { get; }
public AnnotatedTypeSymbol? Type { get; }
public Extraction.Entities.Location Location { get; }
public ExprKind Kind { get; }
@@ -33,25 +33,23 @@ namespace Semmle.Extraction.CSharp.Entities
Location = info.Location;
Kind = info.Kind;
Type = info.Type;
if (Type.Type is null)
Type = NullType.Create(cx);
TryPopulate();
}
protected sealed override void Populate(TextWriter trapFile)
{
trapFile.expressions(this, Kind, Type.Type.TypeRef);
var type = Type.HasValue ? Entities.Type.Create(cx, Type.Value) : NullType.Create(cx);
trapFile.expressions(this, Kind, type.TypeRef);
if (info.Parent.IsTopLevelParent)
trapFile.expr_parent_top_level(this, info.Child, info.Parent);
else
trapFile.expr_parent(this, info.Child, info.Parent);
trapFile.expr_location(this, Location);
var annotatedType = Type.Symbol;
if (!annotatedType.HasObliviousNullability())
if (Type.HasValue && !Type.Value.HasObliviousNullability())
{
var n = NullabilityEntity.Create(cx, Nullability.Create(annotatedType));
var n = NullabilityEntity.Create(cx, Nullability.Create(Type.Value));
trapFile.type_nullability(this, n);
}
@@ -66,7 +64,7 @@ namespace Semmle.Extraction.CSharp.Entities
if (info.ExprValue is string value)
trapFile.expr_value(this, value);
Type.Type.PopulateGenerics();
type.PopulateGenerics();
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => Location.symbol;
@@ -318,6 +316,11 @@ namespace Semmle.Extraction.CSharp.Entities
/// </summary>
public static ExprKind AdjustKind(this Expression.CallType ct, ExprKind k)
{
if (k == ExprKind.ADDRESS_OF)
{
return k;
}
switch (ct)
{
case Expression.CallType.Dynamic:
@@ -367,7 +370,7 @@ namespace Semmle.Extraction.CSharp.Entities
/// <summary>
/// The type of the expression.
/// </summary>
AnnotatedType Type { get; }
AnnotatedTypeSymbol? Type { get; }
/// <summary>
/// The location of the expression.
@@ -411,7 +414,7 @@ namespace Semmle.Extraction.CSharp.Entities
internal class ExpressionInfo : IExpressionInfo
{
public Context Context { get; }
public AnnotatedType Type { get; }
public AnnotatedTypeSymbol? Type { get; }
public Extraction.Entities.Location Location { get; }
public ExprKind Kind { get; }
public IExpressionParentEntity Parent { get; }
@@ -419,7 +422,7 @@ namespace Semmle.Extraction.CSharp.Entities
public bool IsCompilerGenerated { get; }
public string ExprValue { get; }
public ExpressionInfo(Context cx, AnnotatedType type, Extraction.Entities.Location location, ExprKind kind,
public ExpressionInfo(Context cx, AnnotatedTypeSymbol? type, Extraction.Entities.Location location, ExprKind kind,
IExpressionParentEntity parent, int child, bool isCompilerGenerated, string value)
{
Context = cx;
@@ -466,10 +469,15 @@ namespace Semmle.Extraction.CSharp.Entities
public AnnotatedTypeSymbol ResolvedType => new AnnotatedTypeSymbol(TypeInfo.Type.DisambiguateType(), TypeInfo.Nullability.Annotation);
public AnnotatedTypeSymbol ConvertedType => new AnnotatedTypeSymbol(TypeInfo.ConvertedType.DisambiguateType(), TypeInfo.ConvertedNullability.Annotation);
public AnnotatedTypeSymbol ExpressionType
private AnnotatedTypeSymbol? cachedType;
private bool cachedTypeSet;
public AnnotatedTypeSymbol? Type
{
get
{
if (cachedTypeSet)
return cachedType;
var type = ResolvedType;
if (type.Symbol == null)
@@ -491,6 +499,9 @@ namespace Semmle.Extraction.CSharp.Entities
Context.ModelError(Node, "Failed to determine type");
}
cachedType = type;
cachedTypeSet = true;
return type;
}
}
@@ -522,22 +533,6 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
private AnnotatedType cachedType;
public AnnotatedType Type
{
get
{
if (cachedType.Type == null)
cachedType = Entities.Type.Create(Context, ExpressionType);
return cachedType;
}
set
{
cachedType = value;
}
}
private Extraction.Entities.Location cachedLocation;
public Extraction.Entities.Location Location
@@ -572,9 +567,10 @@ namespace Semmle.Extraction.CSharp.Entities
return this;
}
public ExpressionNodeInfo SetType(AnnotatedType type)
public ExpressionNodeInfo SetType(AnnotatedTypeSymbol? type)
{
Type = type;
cachedType = type;
cachedTypeSet = true;
return this;
}

View File

@@ -52,7 +52,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (implicitThis && !symbol.IsStatic)
{
This.CreateImplicit(cx, Entities.Type.Create(cx, symbol.ContainingType), Location, this, -1);
This.CreateImplicit(cx, symbol.ContainingType, Location, this, -1);
}
}

View File

@@ -90,7 +90,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
AnnotatedTypeSymbol.CreateNotAnnotated(type),
location,
ExprKind.ARRAY_CREATION,
parent,

View File

@@ -36,7 +36,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None),
AnnotatedTypeSymbol.CreateNotAnnotated(type),
location,
ExprKind.CAST,
parent,

View File

@@ -12,7 +12,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
private Discard(Context cx, CSharpSyntaxNode syntax, IExpressionParentEntity parent, int child) :
base(new ExpressionInfo(cx, Entities.Type.Create(cx, cx.GetType(syntax)), cx.Create(syntax.GetLocation()), ExprKind.DISCARD, parent, child, false, null))
base(new ExpressionInfo(cx, cx.GetType(syntax), cx.Create(syntax.GetLocation()), ExprKind.DISCARD, parent, child, false, null))
{
}

View File

@@ -12,13 +12,13 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
public ImplicitCast(ExpressionNodeInfo info)
: base(new ExpressionInfo(info.Context, Entities.Type.Create(info.Context, info.ConvertedType), info.Location, ExprKind.CAST, info.Parent, info.Child, true, info.ExprValue))
: base(new ExpressionInfo(info.Context, info.ConvertedType, info.Location, ExprKind.CAST, info.Parent, info.Child, true, info.ExprValue))
{
Expr = Factory.Create(new ExpressionNodeInfo(cx, info.Node, this, 0));
}
public ImplicitCast(ExpressionNodeInfo info, IMethodSymbol method)
: base(new ExpressionInfo(info.Context, Entities.Type.Create(info.Context, info.ConvertedType), info.Location, ExprKind.OPERATOR_INVOCATION, info.Parent, info.Child, true, info.ExprValue))
: base(new ExpressionInfo(info.Context, info.ConvertedType, info.Location, ExprKind.OPERATOR_INVOCATION, info.Parent, info.Child, true, info.ExprValue))
{
Expr = Factory.Create(info.SetParent(this, 0));

View File

@@ -14,7 +14,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
internal class ArrayInitializer : Expression<InitializerExpressionSyntax>
{
private ArrayInitializer(ExpressionNodeInfo info) : base(info.SetType(NullType.Create(info.Context)).SetKind(ExprKind.ARRAY_INIT)) { }
private ArrayInitializer(ExpressionNodeInfo info) : base(info.SetType(null).SetKind(ExprKind.ARRAY_INIT)) { }
public static Expression Create(ExpressionNodeInfo info) => new ArrayInitializer(info).TryPopulate();
@@ -40,7 +40,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
var info = new ExpressionInfo(
cx,
NullType.Create(cx),
null,
location,
ExprKind.ARRAY_INIT,
parent,
@@ -135,7 +135,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
var collectionInfo = cx.GetModel(Syntax).GetCollectionInitializerSymbolInfo(i);
var addMethod = Method.Create(cx, collectionInfo.Symbol as IMethodSymbol);
var voidType = Entities.Type.Create(cx, new AnnotatedTypeSymbol(cx.Compilation.GetSpecialType(SpecialType.System_Void), NullableAnnotation.None));
var voidType = AnnotatedTypeSymbol.CreateNotAnnotated(cx.Compilation.GetSpecialType(SpecialType.System_Void));
var invocation = new Expression(new ExpressionInfo(cx, voidType, cx.Create(i.GetLocation()), ExprKind.METHOD_INVOCATION, this, child++, false, null));

View File

@@ -4,6 +4,7 @@ using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Kinds;
using System.IO;
using System;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -55,7 +56,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
// Implicit `this` qualifier; add explicitly
if (cx.GetModel(Syntax).GetEnclosingSymbol(Location.symbol.SourceSpan.Start) is IMethodSymbol callingMethod)
This.CreateImplicit(cx, Entities.Type.Create(cx, callingMethod.ContainingType), Location, this, child++);
This.CreateImplicit(cx, callingMethod.ContainingType, Location, this, child++);
else
cx.ModelError(Syntax, "Couldn't determine implicit this type");
}
@@ -66,7 +67,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
break;
default:
// Delegate call; `d()`
// Delegate or function pointer call; `d()`
Create(cx, Syntax.Expression, this, child++);
break;
}
@@ -84,7 +85,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (target == null)
{
if (!isDynamicCall && !IsDelegateCall(info))
if (!isDynamicCall && !IsDelegateLikeCall(info))
cx.ModelError(Syntax, "Unable to resolve target for call. (Compilation error?)");
return;
}
@@ -98,7 +99,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
// Either the qualifier (Expression) is dynamic,
// or one of the arguments is dynamic.
var node = (InvocationExpressionSyntax)info.Node;
return !IsDelegateCall(info) &&
return !IsDelegateLikeCall(info) &&
(IsDynamic(info.Context, node.Expression) || node.ArgumentList.Arguments.Any(arg => IsDynamic(info.Context, arg.Expression)));
}
@@ -133,12 +134,22 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
}
private static bool IsDelegateCall(ExpressionNodeInfo info)
private static bool IsDelegateLikeCall(ExpressionNodeInfo info)
{
return IsDelegateLikeCall(info, symbol => IsFunctionPointer(symbol) || IsDelegateInvoke(symbol));
}
private static bool IsDelegateInvokeCall(ExpressionNodeInfo info)
{
return IsDelegateLikeCall(info, IsDelegateInvoke);
}
private static bool IsDelegateLikeCall(ExpressionNodeInfo info, Func<ISymbol, bool> check)
{
var si = info.SymbolInfo;
if (si.CandidateReason == CandidateReason.OverloadResolutionFailure &&
si.CandidateSymbols.OfType<IMethodSymbol>().All(s => s.MethodKind == MethodKind.DelegateInvoke))
si.CandidateSymbols.All(check))
{
return true;
}
@@ -153,9 +164,20 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return true;
}
return si.Symbol != null &&
si.Symbol.Kind == SymbolKind.Method &&
((IMethodSymbol)si.Symbol).MethodKind == MethodKind.DelegateInvoke;
return check(si.Symbol);
}
private static bool IsFunctionPointer(ISymbol symbol)
{
return symbol != null &&
symbol.Kind == SymbolKind.FunctionPointerType;
}
private static bool IsDelegateInvoke(ISymbol symbol)
{
return symbol != null &&
symbol.Kind == SymbolKind.Method &&
((IMethodSymbol)symbol).MethodKind == MethodKind.DelegateInvoke;
}
private static bool IsLocalFunctionInvocation(ExpressionNodeInfo info)
@@ -168,8 +190,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
return IsNameof((InvocationExpressionSyntax)info.Node)
? ExprKind.NAMEOF
: IsDelegateCall(info)
? ExprKind.DELEGATE_INVOCATION
: IsDelegateLikeCall(info)
? IsDelegateInvokeCall(info)
? ExprKind.DELEGATE_INVOCATION
: ExprKind.FUNCTION_POINTER_INVOCATION
: IsLocalFunctionInvocation(info)
? ExprKind.LOCAL_FUNCTION_INVOCATION
: ExprKind.METHOD_INVOCATION;

View File

@@ -21,11 +21,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
case SyntaxKind.DefaultLiteralExpression:
return ExprKind.DEFAULT;
case SyntaxKind.NullLiteralExpression:
info.Type = Entities.NullType.Create(info.Context); // Don't use converted type.
info.SetType(null); // Don't use converted type.
return ExprKind.NULL_LITERAL;
}
var type = info.Type.Type.symbol;
var type = info.Type?.Symbol;
return GetExprKind(type, info.Node, info.Context);
}
@@ -82,7 +82,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
AnnotatedTypeSymbol.CreateNotAnnotated(type),
location,
GetExprKind(type, null, cx),
parent,
@@ -97,7 +97,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
var info = new ExpressionInfo(
cx,
NullType.Create(cx),
null,
location,
ExprKind.NULL_LITERAL,
parent,

View File

@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
// Create an "assignment"
var property = cx.GetModel(init).GetDeclaredSymbol(init);
var propEntity = Property.Create(cx, property);
var type = Entities.Type.Create(cx, property.GetAnnotatedType());
var type = property.GetAnnotatedType();
var loc = cx.Create(init.GetLocation());
var assignment = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.SIMPLE_ASSIGN, objectInitializer, child++, false, null));

View File

@@ -46,10 +46,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
switch (Syntax.Initializer.Kind())
{
case SyntaxKind.CollectionInitializerExpression:
CollectionInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type });
CollectionInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1).SetType(Type));
break;
case SyntaxKind.ObjectInitializerExpression:
ObjectInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type });
ObjectInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1).SetType(Type));
break;
default:
cx.ModelError("Unhandled initializer in object creation");

View File

@@ -20,6 +20,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
case TypePatternSyntax typePattern:
return Expressions.TypeAccess.Create(cx, typePattern.Type, parent, child);
case UnaryPatternSyntax unaryPattern:
return new UnaryPattern(cx, unaryPattern, parent, child);
case DeclarationPatternSyntax declPattern:
// Creates a single local variable declaration.
{
@@ -27,7 +30,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
if (cx.GetModel(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
{
var type = Type.Create(cx, symbol.GetAnnotatedType());
var type = symbol.GetAnnotatedType();
return VariableDeclaration.Create(cx, symbol, type, declPattern.Type, cx.Create(syntax.GetLocation()), false, parent, child);
}
if (designation is DiscardDesignationSyntax)
@@ -42,6 +45,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
case RecursivePatternSyntax recPattern:
return new RecursivePattern(cx, recPattern, parent, child);
case RelationalPatternSyntax relPattern:
return new RelationalPattern(cx, relPattern, parent, child);
case VarPatternSyntax varPattern:
switch (varPattern.Designation)
{
@@ -50,7 +56,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
case SingleVariableDesignationSyntax varDesignation:
if (cx.GetModel(syntax).GetDeclaredSymbol(varDesignation) is ILocalSymbol symbol)
{
var type = Type.Create(cx, symbol.GetAnnotatedType());
var type = symbol.GetAnnotatedType();
return VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), true, parent, child);
}

View File

@@ -7,7 +7,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
internal class PositionalPattern : Expression
{
internal PositionalPattern(Context cx, PositionalPatternClauseSyntax posPc, IExpressionParentEntity parent, int child) :
base(new ExpressionInfo(cx, Entities.NullType.Create(cx), cx.Create(posPc.GetLocation()), ExprKind.POSITIONAL_PATTERN, parent, child, false, null))
base(new ExpressionInfo(cx, null, cx.Create(posPc.GetLocation()), ExprKind.POSITIONAL_PATTERN, parent, child, false, null))
{
child = 0;
foreach (var sub in posPc.Subpatterns)

View File

@@ -7,7 +7,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
internal class PropertyPattern : Expression
{
internal PropertyPattern(Context cx, PropertyPatternClauseSyntax pp, IExpressionParentEntity parent, int child) :
base(new ExpressionInfo(cx, Entities.NullType.Create(cx), cx.Create(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null))
base(new ExpressionInfo(cx, null, cx.Create(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null))
{
child = 0;
var trapFile = cx.TrapWriter.Writer;

View File

@@ -15,9 +15,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
/// <param name="syntax">The syntax node of the recursive pattern.</param>
/// <param name="parent">The parent pattern/expression.</param>
/// <param name="child">The child index of this pattern.</param>
/// <param name="isTopLevel">If this pattern is in the top level of a case/is. In that case, the variable and type access are populated elsewhere.</param>
public RecursivePattern(Context cx, RecursivePatternSyntax syntax, IExpressionParentEntity parent, int child) :
base(new ExpressionInfo(cx, Entities.NullType.Create(cx), cx.Create(syntax.GetLocation()), ExprKind.RECURSIVE_PATTERN, parent, child, false, null))
base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), ExprKind.RECURSIVE_PATTERN, parent, child, false, null))
{
// Extract the type access
if (syntax.Type is TypeSyntax t)
@@ -26,7 +25,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
// Extract the local variable declaration
if (syntax.Designation is VariableDesignationSyntax designation && cx.GetModel(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
{
var type = Entities.Type.Create(cx, symbol.GetAnnotatedType());
var type = symbol.GetAnnotatedType();
VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), false, this, 0);
}

View File

@@ -0,0 +1,29 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Kinds;
using Semmle.Extraction.Entities;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
internal class RelationalPattern : Expression
{
public RelationalPattern(Context cx, RelationalPatternSyntax syntax, IExpressionParentEntity parent, int child) :
base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), GetKind(syntax.OperatorToken), parent, child, false, null))
{
Expression.Create(cx, syntax.Expression, this, 0);
}
private static ExprKind GetKind(SyntaxToken operatorToken)
{
return operatorToken.Kind() switch
{
SyntaxKind.LessThanEqualsToken => ExprKind.LE_PATTERN,
SyntaxKind.GreaterThanEqualsToken => ExprKind.GE_PATTERN,
SyntaxKind.LessThanToken => ExprKind.LT_PATTERN,
SyntaxKind.GreaterThanToken => ExprKind.GT_PATTERN,
_ => throw new InternalError(operatorToken.Parent, $"Relation pattern with operator token '{operatorToken.Kind()}' is not supported."),
};
}
}
}

View File

@@ -0,0 +1,15 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
internal class UnaryPattern : Expression
{
public UnaryPattern(Context cx, UnaryPatternSyntax syntax, IExpressionParentEntity parent, int child) :
base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), ExprKind.NOT_PATTERN, parent, child, false, null))
{
Pattern.Create(cx, syntax.Pattern, this, 0);
}
}
}

View File

@@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
private class QueryCall : Expression
{
public QueryCall(Context cx, IMethodSymbol method, SyntaxNode clause, IExpressionParentEntity parent, int child)
: base(new ExpressionInfo(cx, method is null ? NullType.Create(cx) : Entities.Type.Create(cx, method.GetAnnotatedReturnType()),
: base(new ExpressionInfo(cx, method?.GetAnnotatedReturnType(),
cx.Create(clause.GetLocation()),
ExprKind.METHOD_INVOCATION, parent, child, false, null))
{
@@ -63,21 +63,21 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
protected Expression DeclareRangeVariable(Context cx, IExpressionParentEntity parent, int child, bool getElement, ISymbol variableSymbol, SyntaxToken name)
{
var type = Type.Create(cx, cx.GetType(Expr));
var type = cx.GetType(Expr);
AnnotatedType declType;
AnnotatedTypeSymbol? declType;
TypeSyntax declTypeSyntax = null;
if (getElement)
{
if (node is FromClauseSyntax from && from.Type != null)
{
declTypeSyntax = from.Type;
declType = Type.Create(cx, cx.GetType(from.Type));
declType = cx.GetType(from.Type);
}
else
{
declTypeSyntax = null;
declType = type.Type.ElementType;
declType = GetElementType(cx, type.Symbol);
}
}
else
@@ -104,6 +104,36 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return decl;
}
private static AnnotatedTypeSymbol? GetEnumerableType(Context cx, INamedTypeSymbol type)
{
return type.SpecialType == SpecialType.System_Collections_IEnumerable
? cx.Compilation.ObjectType.WithAnnotation(NullableAnnotation.NotAnnotated)
: type.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T
? type.GetAnnotatedTypeArguments().First()
: (AnnotatedTypeSymbol?)null;
}
private static AnnotatedTypeSymbol? GetEnumerableElementType(Context cx, INamedTypeSymbol type)
{
var et = GetEnumerableType(cx, type);
if (et != null)
return et;
return type.AllInterfaces
.Where(i => i.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T)
.Concat(type.AllInterfaces.Where(i => i.SpecialType == SpecialType.System_Collections_IEnumerable))
.Select(i => GetEnumerableType(cx, i))
.FirstOrDefault();
}
private static AnnotatedTypeSymbol? GetElementType(Context cx, ITypeSymbol symbol) =>
symbol switch
{
IArrayTypeSymbol a => a.GetAnnotatedElementType(),
INamedTypeSymbol n => GetEnumerableElementType(cx, n),
_ => null
};
protected void PopulateArguments(Context cx, QueryCall callExpr, int child)
{
foreach (var e in arguments)

View File

@@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
internal SwitchCase(Context cx, SwitchExpressionArmSyntax arm, Switch parent, int child) :
base(new ExpressionInfo(
cx, Entities.Type.Create(cx, cx.GetType(arm.Expression)), cx.Create(arm.GetLocation()),
cx, cx.GetType(arm.Expression), cx.Create(arm.GetLocation()),
ExprKind.SWITCH_CASE, parent, child, false, null))
{
Expressions.Pattern.Create(cx, arm.Pattern, this, 0);

View File

@@ -7,8 +7,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
private This(IExpressionInfo info) : base(info) { }
public static This CreateImplicit(Context cx, Type @class, Extraction.Entities.Location loc, IExpressionParentEntity parent, int child) =>
new This(new ExpressionInfo(cx, new AnnotatedType(@class, NullableAnnotation.None), loc, Kinds.ExprKind.THIS_ACCESS, parent, child, true, null));
public static This CreateImplicit(Context cx, ITypeSymbol @class, Extraction.Entities.Location loc, IExpressionParentEntity parent, int child) =>
new This(new ExpressionInfo(cx, AnnotatedTypeSymbol.CreateNotAnnotated(@class), loc, Kinds.ExprKind.THIS_ACCESS, parent, child, true, null));
public static This CreateExplicit(ExpressionNodeInfo info) => new This(info.SetKind(ExprKind.THIS_ACCESS));
}

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