Merge branch 'master' into ir-this-parameter-2

This commit is contained in:
Robert Marsh
2020-06-05 13:52:56 -07:00
135 changed files with 3468 additions and 441 deletions

View File

@@ -23,6 +23,9 @@
* TypeScript 3.9 is now supported.
* The analysis of sanitizers has improved, leading to more accurate
results from the security queries.
## New queries
| **Query** | **Tags** | **Purpose** |
@@ -36,15 +39,14 @@
| **Query** | **Expected impact** | **Change** |
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
| Client-side cross-site scripting (`js/xss`) | Fewer results | This query no longer flags optionally sanitized values. |
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Fewer results | This query now recognizes additional safe patterns of doing URL redirects. |
| Client-side cross-site scripting (`js/xss`) | Fewer results | This query now recognizes additional safe patterns of constructing HTML. |
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Fewer results | This query now recognizes additional safe patterns of doing URL redirects. |
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving NoSQL code operators are now recognized. |
| Expression has no effect (`js/useless-expression`) | Fewer results | This query no longer flags an expression when that expression is the only content of the containing file. |
| Hard-coded credentials (`js/hardcoded-credentials`) | More results | This query now recognizes hard-coded credentials sent via HTTP authorization headers. |
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional url scheme checks. |
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes additional utility functions as vulnerable to prototype polution. |
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes more coding patterns that are vulnerable to prototype pollution. |
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
| Unknown directive (`js/unknown-directive`) | Fewer results | This query no longer flags directives generated by the Babel compiler. |

View File

@@ -0,0 +1,22 @@
# Improvements to Python analysis
The following changes in version 1.25 affect Python analysis in all applications.
## General improvements
## New queries
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------|
## Changes to libraries
* Importing `semmle.python.web.HttpRequest` will no longer import `UntrustedStringKind` transitively. `UntrustedStringKind` is the most commonly used non-abstract subclass of `ExternalStringKind`. If not imported (by one mean or another), taint-tracking queries that concern `ExternalStringKind` will not produce any results. Please ensure such queries contain an explicit import (`import semmle.python.security.strings.Untrusted`).

View File

@@ -59,21 +59,32 @@ def file_checksum(filename):
return hashlib.sha1(file_handle.read()).hexdigest()
def check_group(group_name, files, master_file_picker, emit_error):
checksums = {file_checksum(f) for f in files}
if len(checksums) == 1:
extant_files = [f for f in files if path.isfile(f)]
if len(extant_files) == 0:
emit_error(__file__, 0, "No files found from group '" + group_name + "'.")
emit_error(__file__, 0,
"Create one of the following files, and then run this script with "
"the --latest switch to sync it to the other file locations.")
for filename in files:
emit_error(__file__, 0, " " + filename)
return
master_file = master_file_picker(files)
checksums = {file_checksum(f) for f in extant_files}
if len(checksums) == 1 and len(extant_files) == len(files):
# All files are present and identical.
return
master_file = master_file_picker(extant_files)
if master_file is None:
emit_error(__file__, 0,
"Files from group '"+ group_name +"' not in sync.")
emit_error(__file__, 0,
"Run this script with a file-name argument among the "
"following to overwrite the remaining files with the contents "
"of that file or run with the --latest switch to update each "
"of that file, or run with the --latest switch to update each "
"group of files from the most recently modified file in the group.")
for filename in files:
for filename in extant_files:
emit_error(__file__, 0, " " + filename)
else:
print(" Syncing others from", master_file)
@@ -81,7 +92,8 @@ def check_group(group_name, files, master_file_picker, emit_error):
if filename == master_file:
continue
print(" " + filename)
os.replace(filename, filename + '~')
if path.isfile(filename):
os.replace(filename, filename + '~')
shutil.copy(master_file, filename)
print(" Backups written with '~' appended to file names")

View File

@@ -1,3 +1,8 @@
/**
* Provides a class and predicate for recognizing files that are likely to have been generated
* automatically.
*/
import semmle.code.cpp.Comments
import semmle.code.cpp.File
import semmle.code.cpp.Preprocessor

View File

@@ -1,3 +1,7 @@
/**
* Provides classes representing C++ classes, including structs, unions, and template classes.
*/
import semmle.code.cpp.Type
import semmle.code.cpp.UserType
import semmle.code.cpp.metrics.MetricClass

View File

@@ -1,3 +1,7 @@
/**
* Provides classes representing C and C++ comments.
*/
import semmle.code.cpp.Location
import semmle.code.cpp.Element

View File

@@ -1,3 +1,7 @@
/**
* Provides a class representing individual compiler invocations that occurred during the build.
*/
import semmle.code.cpp.File
/*

View File

@@ -1,3 +1,7 @@
/**
* Provides classes for working with C and C++ declarations.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.Specifier
import semmle.code.cpp.Namespace

View File

@@ -1,3 +1,7 @@
/**
* Provides classes representing warnings generated during compilation.
*/
import semmle.code.cpp.Location
/** A compiler-generated error, warning or remark. */

View File

@@ -1,3 +1,8 @@
/**
* Provides the `Element` class, which is the base class for all classes representing C or C++
* program elements.
*/
import semmle.code.cpp.Location
private import semmle.code.cpp.Enclosing
private import semmle.code.cpp.internal.ResolveClass
@@ -261,8 +266,14 @@ private predicate isFromUninstantiatedTemplateRec(Element e, Element template) {
class StaticAssert extends Locatable, @static_assert {
override string toString() { result = "static_assert(..., \"" + getMessage() + "\")" }
/**
* Gets the expression which this static assertion ensures is true.
*/
Expr getCondition() { static_asserts(underlyingElement(this), unresolveElement(result), _, _) }
/**
* Gets the message which will be reported by the compiler if this static assertion fails.
*/
string getMessage() { static_asserts(underlyingElement(this), _, result, _) }
override Location getLocation() { static_asserts(underlyingElement(this), _, _, result) }

View File

@@ -1,3 +1,7 @@
/**
* Provides predicates for finding the smallest element that encloses an expression or statement.
*/
import cpp
/**

View File

@@ -1,3 +1,7 @@
/**
* Provides classes representing C/C++ enums and enum constants.
*/
import semmle.code.cpp.Type
private import semmle.code.cpp.internal.ResolveClass
@@ -19,6 +23,17 @@ class Enum extends UserType, IntegralOrEnumType {
/** Gets an enumerator of this enumeration. */
EnumConstant getAnEnumConstant() { result.getDeclaringEnum() = this }
/**
* Gets the enumerator of this enumeration that was declared at the zero-based position `index`.
* For example, `zero` is at index 2 in the following declaration:
* ```
* enum ReversedOrder {
* two = 2,
* one = 1,
* zero = 0
* };
* ```
*/
EnumConstant getEnumConstant(int index) {
enumconstants(unresolveElement(result), underlyingElement(this), index, _, _, _)
}

View File

@@ -1,3 +1,7 @@
/**
* Provides classes representing C structure members and C++ non-static member variables.
*/
import semmle.code.cpp.Variable
import semmle.code.cpp.Enum
import semmle.code.cpp.exprs.Access

View File

@@ -1,3 +1,7 @@
/**
* Provides classes representing files and folders.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.Declaration
import semmle.code.cpp.metrics.MetricFile

View File

@@ -1,3 +1,7 @@
/**
* Provides a class representing C++ `friend` declarations.
*/
import semmle.code.cpp.Declaration
private import semmle.code.cpp.internal.ResolveClass

View File

@@ -1,3 +1,8 @@
/**
* Provides classes for working with functions, including C++ constructors, destructors,
* user-defined operators, and template functions.
*/
import semmle.code.cpp.Location
import semmle.code.cpp.Member
import semmle.code.cpp.Class
@@ -891,8 +896,10 @@ class Constructor extends MemberFunction {
* A function that defines an implicit conversion.
*/
abstract class ImplicitConversionFunction extends MemberFunction {
/** Gets the type this `ImplicitConversionFunction` takes as input. */
abstract Type getSourceType();
/** Gets the type this `ImplicitConversionFunction` converts to. */
abstract Type getDestType();
}

View File

@@ -1,3 +1,8 @@
/**
* Provides classes representing C/C++ `#include`, `#include_next`, and `#import` preprocessor
* directives.
*/
import semmle.code.cpp.Preprocessor
/**

View File

@@ -67,6 +67,9 @@ private DataFlow::Node getNodeForSource(Expr source) {
// to `gets`. It's impossible here to tell which is which, but the "access
// to argv" source is definitely not intended to match an output argument,
// and it causes false positives if we let it.
//
// This case goes together with the similar (but not identical) rule in
// `nodeIsBarrierIn`.
result = DataFlow::definitionByReferenceNode(source) and
not argv(source.(VariableAccess).getTarget())
)
@@ -202,7 +205,13 @@ private predicate nodeIsBarrier(DataFlow::Node node) {
private predicate nodeIsBarrierIn(DataFlow::Node node) {
// don't use dataflow into taint sources, as this leads to duplicate results.
node = getNodeForSource(any(Expr e))
exists(Expr source | isUserInput(source, _) |
node = DataFlow::exprNode(source)
or
// This case goes together with the similar (but not identical) rule in
// `getNodeForSource`.
node = DataFlow::definitionByReferenceNode(source)
)
}
cached

View File

@@ -8,16 +8,28 @@ private import DataFlowDispatch
* to the callable. Instance arguments (`this` pointer) are also included.
*/
class ArgumentNode extends InstructionNode {
ArgumentNode() { exists(CallInstruction call | this.getInstruction() = call.getAnArgument()) }
ArgumentNode() {
exists(CallInstruction call |
instr = call.getAnArgument()
or
instr.(ReadSideEffectInstruction).getPrimaryInstruction() = call
)
}
/**
* Holds if this argument occurs at the given position in the given call.
* The instance argument is considered to have index `-1`.
*/
predicate argumentOf(DataFlowCall call, int pos) {
this.getInstruction() = call.getPositionalArgument(pos)
instr = call.getPositionalArgument(pos)
or
this.getInstruction() = call.getThisArgument() and pos = -1
instr = call.getThisArgument() and pos = -1
or
exists(ReadSideEffectInstruction read |
read = instr and
read.getPrimaryInstruction() = call and
pos = getArgumentPosOfSideEffect(read.getIndex())
)
}
/** Gets the call in which this node is an argument. */

View File

@@ -54,7 +54,7 @@ class Node extends TIRDataFlowNode {
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
/** Gets the parameter corresponding to this node, if any. */
/** Gets the positional parameter corresponding to this node, if any. */
Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() }
/**
@@ -156,44 +156,90 @@ class ExprNode extends InstructionNode {
}
/**
* A node representing a `Parameter`. This includes both explicit parameters such
* as `x` in `f(x)` and implicit parameters such as `this` in `x.f()`
* INTERNAL: do not use. Translates a parameter/argument index into a negative
* number that denotes the index of its side effect (pointer indirection).
*/
class ParameterNode extends InstructionNode {
override InitializeParameterInstruction instr;
/**
* Holds if this node is the parameter of `c` at the specified (zero-based)
* position. The implicit `this` parameter is considered to have index `-1`.
*/
predicate isParameterOf(Function f, int i) { none() } // overriden by subclasses
bindingset[index]
int getArgumentPosOfSideEffect(int index) {
// -1 -> -2
// 0 -> -3
// 1 -> -4
// ...
result = -3 - index
}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
* flow graph. This includes both explicit parameters such as `x` in `f(x)`
* and implicit parameters such as `this` in `x.f()`.
*
* To match a specific kind of parameter, consider using one of the subclasses
* `ExplicitParameterNode`, `ThisParameterNode`, or
* `ParameterIndirectionNode`.
*/
class ParameterNode extends InstructionNode {
ParameterNode() {
// To avoid making this class abstract, we enumerate its values here
instr instanceof InitializeParameterInstruction
or
instr instanceof InitializeIndirectionInstruction
}
/**
* Holds if this node is the parameter of `f` at the specified position. The
* implicit `this` parameter is considered to have position `-1`, and
* pointer-indirection parameters are at further negative positions.
*/
predicate isParameterOf(Function f, int pos) { none() } // overridden by subclasses
}
/** An explicit positional parameter, not including `this` or `...`. */
private class ExplicitParameterNode extends ParameterNode {
override InitializeParameterInstruction instr;
ExplicitParameterNode() { exists(instr.getParameter()) }
override predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() }
override predicate isParameterOf(Function f, int pos) {
f.getParameter(pos) = instr.getParameter()
}
/** Gets the parameter corresponding to this node. */
/** Gets the `Parameter` associated with this node. */
Parameter getParameter() { result = instr.getParameter() }
override string toString() { result = instr.getParameter().toString() }
}
private class ThisParameterNode extends ParameterNode {
/** An implicit `this` parameter. */
class ThisParameterNode extends ParameterNode {
override InitializeParameterInstruction instr;
ThisParameterNode() { instr.getIRVariable() instanceof IRThisVariable }
override predicate isParameterOf(Function f, int i) {
i = -1 and instr.getEnclosingFunction() = f
override predicate isParameterOf(Function f, int pos) {
pos = -1 and instr.getEnclosingFunction() = f
}
override string toString() { result = "this" }
}
/** A synthetic parameter to model the pointed-to object of a pointer parameter. */
class ParameterIndirectionNode extends ParameterNode {
override InitializeIndirectionInstruction instr;
override predicate isParameterOf(Function f, int pos) {
exists(int index |
f.getParameter(index) = instr.getParameter()
or
index = -1 and
instr.getIRVariable().(IRThisVariable).getEnclosingFunction() = f
|
pos = getArgumentPosOfSideEffect(index)
)
}
override string toString() { result = "*" + instr.getIRVariable().toString() }
}
/**
* DEPRECATED: Data flow was never an accurate way to determine what
* expressions might be uninitialized. It errs on the side of saying that
@@ -341,6 +387,18 @@ class DefinitionByReferenceNode extends InstructionNode {
}
}
/**
* A node representing the memory pointed to by a function argument.
*
* This class exists only in order to override `toString`, which would
* otherwise be the default implementation inherited from `InstructionNode`.
*/
private class ArgumentIndirectionNode extends InstructionNode {
override ReadSideEffectInstruction instr;
override string toString() { result = "Argument " + instr.getIndex() + " indirection" }
}
/**
* A `Node` corresponding to a variable in the program, as opposed to the
* value of that variable at some particular point. This can be used for
@@ -442,6 +500,31 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
or
iTo.(PhiInstruction).getAnOperand().getDef() = iFrom
or
// A read side effect is almost never exact since we don't know exactly how
// much memory the callee will read.
iTo.(ReadSideEffectInstruction).getSideEffectOperand().getAnyDef() = iFrom and
not iFrom.isResultConflated()
or
// Loading a single `int` from an `int *` parameter is not an exact load since
// the parameter may point to an entire array rather than a single `int`. The
// following rule ensures that any flow going into the
// `InitializeIndirectionInstruction`, even if it's for a different array
// element, will propagate to a load of the first element.
//
// Since we're linking `InitializeIndirectionInstruction` and
// `LoadInstruction` together directly, this rule will break if there's any
// reassignment of the parameter indirection, including a conditional one that
// leads to a phi node.
exists(InitializeIndirectionInstruction init |
iFrom = init and
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = init and
// Check that the types match. Otherwise we can get flow from an object to
// its fields, which leads to field conflation when there's flow from other
// fields to the object elsewhere.
init.getParameter().getType().getUnspecifiedType().(DerivedType).getBaseType() =
iTo.getResultType().getUnspecifiedType()
)
or
// Treat all conversions as flow, even conversions between different numeric types.
iTo.(ConvertInstruction).getUnary() = iFrom
or

View File

@@ -56,7 +56,7 @@ class ValueNumber extends TValueNumber {
or
this instanceof TInitializeParameterValueNumber and result = "InitializeParameter"
or
this instanceof TInitializeThisValueNumber and result = "InitializeThis"
this instanceof TConstantValueNumber and result = "Constant"
or
this instanceof TStringConstantValueNumber and result = "StringConstant"
or

View File

@@ -7,7 +7,6 @@ newtype TValueNumber =
TInitializeParameterValueNumber(IRFunction irFunc, Language::AST var) {
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
@@ -79,8 +78,6 @@ private predicate numberableInstruction(Instruction instr) {
or
instr instanceof InitializeParameterInstruction
or
instr instanceof InitializeThisInstruction
or
instr instanceof ConstantInstruction
or
instr instanceof StringConstantInstruction
@@ -132,10 +129,6 @@ private predicate initializeParameterValueNumber(
instr.getIRVariable().getAST() = var
}
private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc
}
private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
@@ -268,9 +261,6 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
result = TInitializeParameterValueNumber(irFunc, var)
)
or
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(string value, IRType type |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)

View File

@@ -56,7 +56,7 @@ class ValueNumber extends TValueNumber {
or
this instanceof TInitializeParameterValueNumber and result = "InitializeParameter"
or
this instanceof TInitializeThisValueNumber and result = "InitializeThis"
this instanceof TConstantValueNumber and result = "Constant"
or
this instanceof TStringConstantValueNumber and result = "StringConstant"
or

View File

@@ -7,7 +7,6 @@ newtype TValueNumber =
TInitializeParameterValueNumber(IRFunction irFunc, Language::AST var) {
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
@@ -79,8 +78,6 @@ private predicate numberableInstruction(Instruction instr) {
or
instr instanceof InitializeParameterInstruction
or
instr instanceof InitializeThisInstruction
or
instr instanceof ConstantInstruction
or
instr instanceof StringConstantInstruction
@@ -132,10 +129,6 @@ private predicate initializeParameterValueNumber(
instr.getIRVariable().getAST() = var
}
private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc
}
private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
@@ -268,9 +261,6 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
result = TInitializeParameterValueNumber(irFunc, var)
)
or
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(string value, IRType type |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)

View File

@@ -1698,7 +1698,8 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect
else
if index = 1 and expr.hasAlignedAllocation()
then result = getTranslatedExpr(expr.getAlignmentArgument())
else result = getTranslatedExpr(expr.getAllocatorCall().getArgument(index))
else
result = getTranslatedExpr(expr.getAllocatorCall().getArgument(index).getFullyConverted())
}
}

View File

@@ -56,7 +56,7 @@ class ValueNumber extends TValueNumber {
or
this instanceof TInitializeParameterValueNumber and result = "InitializeParameter"
or
this instanceof TInitializeThisValueNumber and result = "InitializeThis"
this instanceof TConstantValueNumber and result = "Constant"
or
this instanceof TStringConstantValueNumber and result = "StringConstant"
or

View File

@@ -7,7 +7,6 @@ newtype TValueNumber =
TInitializeParameterValueNumber(IRFunction irFunc, Language::AST var) {
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
@@ -79,8 +78,6 @@ private predicate numberableInstruction(Instruction instr) {
or
instr instanceof InitializeParameterInstruction
or
instr instanceof InitializeThisInstruction
or
instr instanceof ConstantInstruction
or
instr instanceof StringConstantInstruction
@@ -132,10 +129,6 @@ private predicate initializeParameterValueNumber(
instr.getIRVariable().getAST() = var
}
private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc
}
private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
@@ -268,9 +261,6 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
result = TInitializeParameterValueNumber(irFunc, var)
)
or
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(string value, IRType type |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)

View File

@@ -84,8 +84,6 @@ class GVN extends TValueNumber {
or
this instanceof TInitializeParameterValueNumber and result = "InitializeParameter"
or
this instanceof TInitializeThisValueNumber and result = "InitializeThis"
or
this instanceof TStringConstantValueNumber and result = "StringConstant"
or
this instanceof TFieldAddressValueNumber and result = "FieldAddress"

View File

@@ -117,3 +117,35 @@ void test_conflated_fields3() {
taint_y(&xy);
sink(xy.x); // not tainted
}
struct Point {
int x;
int y;
void callSink() {
sink(this->x); // tainted
sink(this->y); // not tainted
}
};
void test_conflated_fields1() {
Point p;
p.x = getenv("VAR")[0];
sink(p.x); // tainted
sink(p.y); // not tainted
p.callSink();
}
void taint_x(Point *pp) {
pp->x = getenv("VAR")[0];
}
void y_to_sink(Point *pp) {
sink(pp->y); // not tainted
}
void test_conflated_fields2() {
Point p;
taint_x(&p);
y_to_sink(&p);
}

View File

@@ -103,6 +103,18 @@
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:110:17:110:32 | (int)... |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:110:17:110:32 | access to array |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:111:12:111:18 | tainted |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | defaulttainttracking.cpp:126:16:126:16 | x |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | defaulttainttracking.cpp:133:9:133:14 | call to getenv |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | defaulttainttracking.cpp:133:9:133:24 | (int)... |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | defaulttainttracking.cpp:133:9:133:24 | access to array |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | defaulttainttracking.cpp:134:10:134:10 | x |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | shared.h:6:15:6:23 | sinkparam |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:140:11:140:16 | call to getenv |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:140:11:140:26 | (int)... |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:140:11:140:26 | access to array |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:143:23:143:24 | pp |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:144:8:144:9 | pp |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:150:13:150:14 | & ... |
| dispatch.cpp:28:29:28:34 | call to getenv | dispatch.cpp:28:24:28:27 | call to atoi |
| dispatch.cpp:28:29:28:34 | call to getenv | dispatch.cpp:28:29:28:34 | call to getenv |
| dispatch.cpp:28:29:28:34 | call to getenv | dispatch.cpp:28:29:28:45 | (const char *)... |

View File

@@ -21,6 +21,14 @@
| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:98:10:98:11 | p2 | IR only |
| defaulttainttracking.cpp:97:27:97:32 | call to getenv | shared.h:5:23:5:31 | sinkparam | IR only |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:111:8:111:8 | y | AST only |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | defaulttainttracking.cpp:126:16:126:16 | x | IR only |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | defaulttainttracking.cpp:133:5:133:5 | x | AST only |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | defaulttainttracking.cpp:134:10:134:10 | x | IR only |
| defaulttainttracking.cpp:133:9:133:14 | call to getenv | shared.h:6:15:6:23 | sinkparam | IR only |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:140:7:140:7 | x | AST only |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:143:23:143:24 | pp | IR only |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:144:8:144:9 | pp | IR only |
| defaulttainttracking.cpp:140:11:140:16 | call to getenv | defaulttainttracking.cpp:150:13:150:14 | & ... | IR only |
| globals.cpp:13:15:13:20 | call to getenv | globals.cpp:13:5:13:11 | global1 | AST only |
| globals.cpp:23:15:23:20 | call to getenv | globals.cpp:23:5:23:11 | global2 | AST only |
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) | IR only |

View File

@@ -27,7 +27,7 @@ void following_pointers(
sourceStruct1_ptr->m1 = source();
sink(sourceStruct1_ptr->m1); // flow
sink(sourceStruct1_ptr->getFirst()); // flow [NOT DETECTED with IR]
sink(sourceStruct1_ptr->getFirst()); // flow
sink(sourceStruct1_ptr->m2); // no flow
sink(sourceStruct1.m1); // no flow

View File

@@ -366,7 +366,7 @@ class FlowThroughFields {
}
int calledAfterTaint() {
sink(field); // tainted [NOT DETECTED with IR]
sink(field); // tainted
}
int taintAndCall() {

View File

@@ -1,7 +1,6 @@
| BarrierGuard.cpp:49:10:49:15 | BarrierGuard.cpp:51:13:51:13 | AST only |
| BarrierGuard.cpp:60:11:60:16 | BarrierGuard.cpp:62:14:62:14 | AST only |
| clang.cpp:12:9:12:20 | clang.cpp:22:8:22:20 | AST only |
| clang.cpp:28:27:28:32 | clang.cpp:30:27:30:34 | AST only |
| clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only |
| dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only |
| dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only |
@@ -19,11 +18,7 @@
| dispatch.cpp:144:8:144:13 | dispatch.cpp:96:8:96:8 | IR only |
| globals.cpp:13:23:13:28 | globals.cpp:12:10:12:24 | IR only |
| globals.cpp:23:23:23:28 | globals.cpp:19:10:19:24 | IR only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:29:3:29:6 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:41:8:41:8 | AST only |
| lambdas.cpp:43:7:43:12 | lambdas.cpp:46:7:46:7 | AST only |
| ref.cpp:29:11:29:16 | ref.cpp:62:10:62:11 | AST only |
| ref.cpp:53:9:53:10 | ref.cpp:56:10:56:11 | AST only |
@@ -39,7 +34,6 @@
| test.cpp:109:9:109:14 | test.cpp:110:10:110:12 | IR only |
| test.cpp:347:17:347:22 | test.cpp:349:10:349:18 | AST only |
| test.cpp:359:13:359:18 | test.cpp:365:10:365:14 | AST only |
| test.cpp:373:13:373:18 | test.cpp:369:10:369:14 | AST only |
| test.cpp:399:7:399:9 | test.cpp:401:8:401:10 | AST only |
| test.cpp:405:7:405:9 | test.cpp:408:8:408:10 | AST only |
| test.cpp:416:7:416:11 | test.cpp:418:8:418:12 | AST only |

View File

@@ -12,6 +12,7 @@
| clang.cpp:18:8:18:19 | (const int *)... | clang.cpp:12:9:12:20 | sourceArray1 |
| clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 |
| clang.cpp:29:27:29:28 | m1 | clang.cpp:28:27:28:32 | call to source |
| clang.cpp:30:27:30:34 | call to getFirst | clang.cpp:28:27:28:32 | call to source |
| clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source |
| clang.cpp:41:18:41:19 | m2 | clang.cpp:39:42:39:47 | call to source |
| clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source |
@@ -38,7 +39,11 @@
| globals.cpp:6:10:6:14 | local | globals.cpp:5:17:5:22 | call to source |
| globals.cpp:12:10:12:24 | flowTestGlobal1 | globals.cpp:13:23:13:28 | call to source |
| globals.cpp:19:10:19:24 | flowTestGlobal2 | globals.cpp:23:23:23:28 | call to source |
| lambdas.cpp:14:3:14:6 | t | lambdas.cpp:8:10:8:15 | call to source |
| lambdas.cpp:18:8:18:8 | call to operator() | lambdas.cpp:8:10:8:15 | call to source |
| lambdas.cpp:29:3:29:6 | t | lambdas.cpp:8:10:8:15 | call to source |
| lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source |
| lambdas.cpp:41:8:41:8 | (reference dereference) | lambdas.cpp:8:10:8:15 | call to source |
| ref.cpp:123:13:123:15 | val | ref.cpp:122:23:122:28 | call to source |
| ref.cpp:126:13:126:15 | val | ref.cpp:125:19:125:24 | call to source |
| ref.cpp:129:13:129:15 | val | ref.cpp:94:15:94:20 | call to source |
@@ -65,6 +70,7 @@
| test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source |
| test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source |
| test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source |
| test.cpp:369:10:369:14 | field | test.cpp:373:13:373:18 | call to source |
| test.cpp:375:10:375:14 | field | test.cpp:373:13:373:18 | call to source |
| test.cpp:385:8:385:10 | tmp | test.cpp:382:48:382:54 | source1 |
| test.cpp:392:8:392:10 | tmp | test.cpp:388:53:388:59 | source1 |

View File

@@ -104,7 +104,7 @@ public:
{
if (C1 *c1 = dynamic_cast<C1 *>(c))
{
sink(c1->a); // $ast $f-:ir
sink(c1->a); // $ast $ir
}
C *cc;
if (C2 *c2 = dynamic_cast<C2 *>(c))

View File

@@ -0,0 +1,32 @@
private import semmle.code.cpp.dataflow.DataFlow
private import DataFlow
class Conf extends Configuration {
Conf() { this = "FieldFlowConf" }
override predicate isSource(Node src) {
src.asExpr() instanceof NewExpr
or
src.asExpr().(Call).getTarget().hasName("user_input")
or
exists(FunctionCall fc |
fc.getAnArgument() = src.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}
override predicate isSink(Node sink) {
exists(Call c |
c.getTarget().hasName("sink") and
c.getAnArgument() = sink.asExpr()
)
}
override predicate isAdditionalFlowStep(Node a, Node b) {
b.asPartialDefinition() =
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
.getQualifier()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}
}

View File

@@ -0,0 +1,32 @@
private import semmle.code.cpp.ir.dataflow.DataFlow
private import DataFlow
class Conf extends Configuration {
Conf() { this = "FieldFlowConf" }
override predicate isSource(Node src) {
src.asExpr() instanceof NewExpr
or
src.asExpr().(Call).getTarget().hasName("user_input")
or
exists(FunctionCall fc |
fc.getAnArgument() = src.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}
override predicate isSink(Node sink) {
exists(Call c |
c.getTarget().hasName("sink") and
c.getAnArgument() = sink.asExpr()
)
}
override predicate isAdditionalFlowStep(Node a, Node b) {
b.asPartialDefinition() =
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
.getQualifier()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}
}

View File

@@ -66,7 +66,7 @@ void test_setThroughNonMember() {
void test_nonMemberSetA() {
S s;
nonMemberSetA(&s, user_input());
sink(nonMemberGetA(&s)); // $ast $f-:ir
sink(nonMemberGetA(&s)); // $ast,ir
}
////////////////////

View File

@@ -4,49 +4,19 @@
import TestUtilities.InlineExpectationsTest
import semmle.code.cpp.dataflow.DataFlow
import DataFlow
import ASTConfiguration
import cpp
class Conf extends Configuration {
Conf() { this = "FieldFlowConf" }
override predicate isSource(Node src) {
src.asExpr() instanceof NewExpr
or
src.asExpr().(Call).getTarget().hasName("user_input")
or
exists(FunctionCall fc |
fc.getAnArgument() = src.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}
override predicate isSink(Node sink) {
exists(Call c |
c.getTarget().hasName("sink") and
c.getAnArgument() = sink.asExpr()
)
}
override predicate isAdditionalFlowStep(Node a, Node b) {
b.asPartialDefinition() =
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
.getQualifier()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}
}
class ASTFieldFlowTest extends InlineExpectationsTest {
ASTFieldFlowTest() { this = "ASTFieldFlowTest" }
override string getARelevantTag() { result = "ast" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Node source, Node sink, Conf conf, int n |
exists(DataFlow::Node source, DataFlow::Node sink, Conf conf, int n |
tag = "ast" and
conf.hasFlow(source, sink) and
n = strictcount(Node otherSource | conf.hasFlow(otherSource, sink)) and
n = strictcount(DataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and
(
n = 1 and value = ""
or

View File

@@ -4,49 +4,19 @@
import TestUtilities.InlineExpectationsTest
import semmle.code.cpp.ir.dataflow.DataFlow
import DataFlow
import IRConfiguration
import cpp
class Conf extends Configuration {
Conf() { this = "FieldFlowConf" }
override predicate isSource(Node src) {
src.asExpr() instanceof NewExpr
or
src.asExpr().(Call).getTarget().hasName("user_input")
or
exists(FunctionCall fc |
fc.getAnArgument() = src.asDefiningArgument() and
fc.getTarget().hasName("argument_source")
)
}
override predicate isSink(Node sink) {
exists(Call c |
c.getTarget().hasName("sink") and
c.getAnArgument() = sink.asExpr()
)
}
override predicate isAdditionalFlowStep(Node a, Node b) {
b.asPartialDefinition() =
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
.getQualifier()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}
}
class IRFieldFlowTest extends InlineExpectationsTest {
IRFieldFlowTest() { this = "IRFieldFlowTest" }
override string getARelevantTag() { result = "ir" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Node source, Node sink, Conf conf, int n |
exists(DataFlow::Node source, DataFlow::Node sink, Conf conf, int n |
tag = "ir" and
conf.hasFlow(source, sink) and
n = strictcount(Node otherSource | conf.hasFlow(otherSource, sink)) and
n = strictcount(DataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and
(
n = 1 and value = ""
or

View File

@@ -0,0 +1,182 @@
edges
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Store |
| A.cpp:100:5:100:13 | Chi [a] | A.cpp:101:8:101:9 | Argument 0 indirection [a] |
| A.cpp:100:5:100:13 | Store | A.cpp:100:5:100:13 | Chi [a] |
| A.cpp:101:8:101:9 | Argument 0 indirection [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:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a |
| A.cpp:107:16:107:16 | a | A.cpp:107:12:107:16 | (void *)... |
| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] |
| A.cpp:142:7:142:20 | Store | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Store |
| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c |
| 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:154:13:154:13 | c | A.cpp:154:10:154:13 | (void *)... |
| aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] |
| aliasing.cpp:9:3:9:22 | Store | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Store |
| aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] |
| aliasing.cpp:13:3:13:21 | Store | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Store |
| 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: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:3:60:22 | Store | aliasing.cpp:60:3:60:22 | Chi [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Store |
| aliasing.cpp:61:13:61:14 | Store [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 |
| by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | by_reference.cpp:69:22:69:23 | Argument 0 indirection [a] |
| 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:69:22:69:23 | Argument 0 indirection [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
| 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:3:84:25 | Store | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | Store |
| 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:3:88:24 | Store | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | Store |
| 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: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: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: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] |
| 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 | Argument -1 indirection [f1] |
| simple.cpp:83:9:83:28 | Store | simple.cpp:83:9:83:28 | Chi [f1] |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Store |
| simple.cpp:84:14:84:20 | Argument -1 indirection [f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:20:20:29 | Chi [a] | struct_init.c:24:10:24:12 | Argument 0 indirection [a] |
| struct_init.c:20:20:20:29 | Store | struct_init.c:20:20:20:29 | Chi [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | Store |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a |
| struct_init.c:24:10:24:12 | Argument 0 indirection [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:27:7:27:16 | Chi [a] | struct_init.c:36:10:36:24 | Argument 0 indirection [a] |
| struct_init.c:27:7:27:16 | Store | struct_init.c:27:7:27:16 | Chi [a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | Store |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a |
| struct_init.c:36:10:36:24 | Argument 0 indirection [a] | struct_init.c:14:24:14:25 | *ab [a] |
nodes
| 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:5:100:13 | Store | semmle.label | Store |
| A.cpp:101:8:101:9 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] |
| A.cpp:103:14:103:14 | *c [a] | semmle.label | *c [a] |
| A.cpp:107:12:107:16 | (void *)... | semmle.label | (void *)... |
| A.cpp:107:16:107:16 | a | semmle.label | a |
| A.cpp:107:16:107:16 | a | semmle.label | a |
| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:142:7:142:20 | Store | semmle.label | Store |
| A.cpp:142:14:142:20 | new | semmle.label | new |
| 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:154:10:154:13 | (void *)... | semmle.label | (void *)... |
| A.cpp:154:13:154:13 | c | semmle.label | c |
| A.cpp:154:13:154:13 | c | semmle.label | c |
| aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:9:3:9:22 | Store | semmle.label | Store |
| 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:3:13:21 | Store | semmle.label | Store |
| 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:30:11:30:12 | m1 | semmle.label | 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:3:60:22 | Store | semmle.label | Store |
| 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: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 |
| by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | semmle.label | nonMemberSetA output argument [a] |
| 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:69:22:69:23 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:84:3:84:25 | Store | semmle.label | Store |
| 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:3:88:24 | Store | semmle.label | Store |
| by_reference.cpp:88:13:88:22 | 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:106:21:106:41 | Chi [a] | semmle.label | Chi [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:110:27:110:27 | a | semmle.label | a |
| by_reference.cpp:114:29:114:29 | a | semmle.label | a |
| by_reference.cpp:122:21:122:38 | Chi [a] | semmle.label | Chi [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:126:21:126:40 | Chi [a] | semmle.label | Chi [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:130:27:130:27 | a | semmle.label | a |
| by_reference.cpp:134:29:134:29 | a | semmle.label | a |
| simple.cpp:65:5:65:22 | Store [i] | semmle.label | Store [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:83:9:83:28 | Store | semmle.label | Store |
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:84:14:84:20 | Argument -1 indirection [f1] | semmle.label | Argument -1 indirection [f1] |
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
| 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:20:20:20:29 | Store | semmle.label | Store |
| 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:24:10:24:12 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] |
| struct_init.c:27:7:27:16 | Chi [a] | semmle.label | Chi [a] |
| struct_init.c:27:7:27:16 | Store | semmle.label | Store |
| 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:10:36:24 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] |
#select
| A.cpp:107:12:107:16 | (void *)... | A.cpp:98:12:98:18 | new | A.cpp:107:12:107:16 | (void *)... | (void *)... flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:107:16:107:16 | a | A.cpp:98:12:98:18 | new | A.cpp:107:16:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:154:10:154:13 | (void *)... | A.cpp:142:14:142:20 | new | A.cpp:154:10:154:13 | (void *)... | (void *)... flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input |
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input |
| aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input | call to user_input |
| aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input | call to user_input |
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input |
| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input | call to user_input |
| aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input | call to user_input |
| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input |
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | call to nonMemberGetA flows from $@ | by_reference.cpp:68:21:68:30 | call to user_input | call to user_input |
| by_reference.cpp:110:27:110:27 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:110:27:110:27 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
| by_reference.cpp:114:29:114:29 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:114:29:114:29 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
| by_reference.cpp:130:27:130:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:130:27:130:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp: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 |
| 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 |
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |

View File

@@ -0,0 +1,12 @@
/**
* @kind path-problem
*/
import semmle.code.cpp.ir.dataflow.DataFlow
import IRConfiguration
import cpp
import DataFlow::PathGraph
from DataFlow::PathNode src, DataFlow::PathNode sink, Conf conf
where conf.hasFlowPath(src, sink)
select sink, src, sink, sink + " flows from $@", src, src.toString()

View File

@@ -0,0 +1,838 @@
edges
| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... |
| A.cpp:47:12:47:18 | new | A.cpp:48:20:48:20 | c |
| A.cpp:48:12:48:18 | call to make [c] | A.cpp:49:10:49:10 | b [c] |
| A.cpp:48:20:48:20 | c | A.cpp:48:12:48:18 | call to make [c] |
| A.cpp:49:10:49:10 | b [c] | A.cpp:49:13:49:13 | c |
| A.cpp:55:5:55:5 | ref arg b [c] | A.cpp:56:10:56:10 | b [c] |
| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | ref arg b [c] |
| A.cpp:56:10:56:10 | b [c] | A.cpp:56:13:56:15 | call to get |
| A.cpp:57:11:57:24 | call to B [c] | A.cpp:57:11:57:24 | new [c] |
| A.cpp:57:11:57:24 | new [c] | A.cpp:57:28:57:30 | call to get |
| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | call to B [c] |
| A.cpp:64:10:64:15 | call to setOnB [c] | A.cpp:66:10:66:11 | b2 [c] |
| A.cpp:64:21:64:28 | new | A.cpp:64:10:64:15 | call to setOnB [c] |
| A.cpp:66:10:66:11 | b2 [c] | A.cpp:66:14:66:14 | c |
| A.cpp:73:10:73:19 | call to setOnBWrap [c] | A.cpp:75:10:75:11 | b2 [c] |
| A.cpp:73:25:73:32 | new | A.cpp:73:10:73:19 | call to setOnBWrap [c] |
| A.cpp:75:10:75:11 | b2 [c] | A.cpp:75:14:75:14 | c |
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | ... = ... |
| A.cpp:100:5:100:6 | c1 [post update] [a] | A.cpp:101:8:101:9 | c1 [a] |
| A.cpp:100:5:100:13 | ... = ... | A.cpp:100:5:100:6 | c1 [post update] [a] |
| A.cpp:101:8:101:9 | c1 [a] | A.cpp:103:14:103:14 | c [a] |
| A.cpp:103:14:103:14 | c [a] | A.cpp:107:12:107:13 | c1 [a] |
| A.cpp:103:14:103:14 | c [a] | A.cpp:120:12:120:13 | c1 [a] |
| A.cpp:107:12:107:13 | c1 [a] | A.cpp:107:16:107:16 | a |
| A.cpp:120:12:120:13 | c1 [a] | A.cpp:120:16:120:16 | a |
| A.cpp:126:5:126:5 | ref arg b [c] | A.cpp:131:8:131:8 | ref arg b [c] |
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | ref arg b [c] |
| A.cpp:131:8:131:8 | ref arg b [c] | A.cpp:132:10:132:10 | b [c] |
| A.cpp:132:10:132:10 | b [c] | A.cpp:132:13:132:13 | c |
| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:143:7:143:31 | ... = ... [c] |
| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:151:18:151:18 | ref arg b [c] |
| A.cpp:142:7:142:20 | ... = ... | A.cpp:142:7:142:7 | b [post update] [c] |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | ... = ... |
| A.cpp:143:7:143:10 | this [post update] [b, c] | A.cpp:151:12:151:24 | call to D [b, c] |
| A.cpp:143:7:143:10 | this [post update] [b] | A.cpp:151:12:151:24 | call to D [b] |
| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:7:143:10 | this [post update] [b] |
| A.cpp:143:7:143:31 | ... = ... [c] | A.cpp:143:7:143:10 | this [post update] [b, c] |
| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | ... = ... |
| A.cpp:150:12:150:18 | new | A.cpp:151:18:151:18 | b |
| A.cpp:151:12:151:24 | call to D [b, c] | A.cpp:153:10:153:10 | d [b, c] |
| A.cpp:151:12:151:24 | call to D [b] | A.cpp:152:10:152:10 | d [b] |
| A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | call to D [b] |
| A.cpp:151:18:151:18 | ref arg b [c] | A.cpp:154:10:154:10 | b [c] |
| A.cpp:152:10:152:10 | d [b] | A.cpp:152:13:152:13 | b |
| A.cpp:153:10:153:10 | d [b, c] | A.cpp:153:13:153:13 | b [c] |
| A.cpp:153:13:153:13 | b [c] | A.cpp:153:16:153:16 | c |
| A.cpp:154:10:154:10 | b [c] | A.cpp:154:13:154:13 | c |
| A.cpp:159:12:159:18 | new | A.cpp:160:29:160:29 | b |
| A.cpp:160:18:160:60 | call to MyList [head] | A.cpp:161:38:161:39 | l1 [head] |
| A.cpp:160:29:160:29 | b | A.cpp:160:18:160:60 | call to MyList [head] |
| A.cpp:161:18:161:40 | call to MyList [next, head] | A.cpp:162:38:162:39 | l2 [next, head] |
| A.cpp:161:38:161:39 | l1 [head] | A.cpp:161:18:161:40 | call to MyList [next, head] |
| A.cpp:162:18:162:40 | call to MyList [next, next, ... (3)] | A.cpp:165:10:165:11 | l3 [next, next, ... (3)] |
| A.cpp:162:18:162:40 | call to MyList [next, next, ... (3)] | A.cpp:167:44:167:44 | l [next, next, ... (3)] |
| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:162:18:162:40 | call to MyList [next, next, ... (3)] |
| A.cpp:165:10:165:11 | l3 [next, next, ... (3)] | A.cpp:165:14:165:17 | next [next, head] |
| A.cpp:165:14:165:17 | next [next, head] | A.cpp:165:20:165:23 | next [head] |
| A.cpp:165:20:165:23 | next [head] | A.cpp:165:26:165:29 | head |
| A.cpp:167:44:167:44 | l [next, head] | A.cpp:167:47:167:50 | next [head] |
| A.cpp:167:44:167:44 | l [next, next, ... (3)] | A.cpp:167:47:167:50 | next [next, head] |
| A.cpp:167:47:167:50 | next [head] | A.cpp:169:12:169:12 | l [head] |
| A.cpp:167:47:167:50 | next [next, head] | A.cpp:167:44:167:44 | l [next, head] |
| A.cpp:169:12:169:12 | l [head] | A.cpp:169:15:169:18 | head |
| B.cpp:6:15:6:24 | new | B.cpp:7:25:7:25 | e |
| B.cpp:7:16:7:35 | call to Box1 [elem1] | B.cpp:8:25:8:26 | b1 [elem1] |
| B.cpp:7:25:7:25 | e | B.cpp:7:16:7:35 | call to Box1 [elem1] |
| B.cpp:8:16:8:27 | call to Box2 [box1, elem1] | B.cpp:9:10:9:11 | b2 [box1, elem1] |
| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:8:16:8:27 | call to Box2 [box1, elem1] |
| B.cpp:9:10:9:11 | b2 [box1, elem1] | B.cpp:9:14:9:17 | box1 [elem1] |
| B.cpp:9:14:9:17 | box1 [elem1] | B.cpp:9:20:9:24 | elem1 |
| B.cpp:15:15:15:27 | new | B.cpp:16:37:16:37 | e |
| B.cpp:16:16:16:38 | call to Box1 [elem2] | B.cpp:17:25:17:26 | b1 [elem2] |
| B.cpp:16:37:16:37 | e | B.cpp:16:16:16:38 | call to Box1 [elem2] |
| B.cpp:17:16:17:27 | call to Box2 [box1, elem2] | B.cpp:19:10:19:11 | b2 [box1, elem2] |
| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:17:16:17:27 | call to Box2 [box1, elem2] |
| B.cpp:19:10:19:11 | b2 [box1, elem2] | B.cpp:19:14:19:17 | box1 [elem2] |
| B.cpp:19:14:19:17 | box1 [elem2] | B.cpp:19:20:19:24 | elem2 |
| C.cpp:18:12:18:18 | call to C [s1] | C.cpp:19:5:19:5 | c [s1] |
| C.cpp:18:12:18:18 | call to C [s3] | C.cpp:19:5:19:5 | c [s3] |
| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | this [s1] |
| C.cpp:19:5:19:5 | c [s3] | C.cpp:27:8:27:11 | this [s3] |
| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | C.cpp:18:12:18:18 | call to C [s1] |
| C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] |
| C.cpp:24:5:24:8 | this [post update] [s3] | C.cpp:18:12:18:18 | call to C [s3] |
| C.cpp:24:5:24:25 | ... = ... | C.cpp:24:5:24:8 | this [post update] [s3] |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | ... = ... |
| C.cpp:27:8:27:11 | this [s1] | C.cpp:29:10:29:11 | this [s1] |
| C.cpp:27:8:27:11 | this [s3] | C.cpp:31:10:31:11 | this [s3] |
| C.cpp:29:10:29:11 | this [s1] | C.cpp:29:10:29:11 | s1 |
| C.cpp:31:10:31:11 | this [s3] | C.cpp:31:10:31:11 | s3 |
| D.cpp:21:30:21:31 | b2 [box, elem] | D.cpp:22:10:22:11 | b2 [box, elem] |
| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:22:14:22:20 | call to getBox1 [elem] |
| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:22:25:22:31 | call to getElem |
| D.cpp:28:15:28:24 | new | D.cpp:30:5:30:20 | ... = ... |
| D.cpp:30:5:30:5 | b [post update] [box, elem] | D.cpp:31:14:31:14 | b [box, elem] |
| D.cpp:30:5:30:20 | ... = ... | D.cpp:30:8:30:10 | box [post update] [elem] |
| D.cpp:30:8:30:10 | box [post update] [elem] | D.cpp:30:5:30:5 | b [post update] [box, elem] |
| D.cpp:31:14:31:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] |
| D.cpp:35:15:35:24 | new | D.cpp:37:21:37:21 | e |
| D.cpp:37:5:37:5 | b [post update] [box, elem] | D.cpp:38:14:38:14 | b [box, elem] |
| D.cpp:37:8:37:10 | ref arg box [elem] | D.cpp:37:5:37:5 | b [post update] [box, elem] |
| D.cpp:37:21:37:21 | e | D.cpp:37:8:37:10 | ref arg box [elem] |
| D.cpp:38:14:38:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] |
| D.cpp:42:15:42:24 | new | D.cpp:44:5:44:26 | ... = ... |
| D.cpp:44:5:44:5 | ref arg b [box, elem] | D.cpp:45:14:45:14 | b [box, elem] |
| D.cpp:44:5:44:26 | ... = ... | D.cpp:44:8:44:14 | call to getBox1 [post update] [elem] |
| D.cpp:44:8:44:14 | call to getBox1 [post update] [elem] | D.cpp:44:5:44:5 | ref arg b [box, elem] |
| D.cpp:45:14:45:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] |
| D.cpp:49:15:49:24 | new | D.cpp:51:27:51:27 | e |
| D.cpp:51:5:51:5 | ref arg b [box, elem] | D.cpp:52:14:52:14 | b [box, elem] |
| D.cpp:51:8:51:14 | ref arg call to getBox1 [elem] | D.cpp:51:5:51:5 | ref arg b [box, elem] |
| D.cpp:51:27:51:27 | e | D.cpp:51:8:51:14 | ref arg call to getBox1 [elem] |
| D.cpp:52:14:52:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] |
| D.cpp:56:15:56:24 | new | D.cpp:58:5:58:27 | ... = ... |
| D.cpp:58:5:58:12 | boxfield [post update] [box, elem] | D.cpp:58:5:58:12 | this [post update] [boxfield, box, ... (3)] |
| D.cpp:58:5:58:12 | this [post update] [boxfield, box, ... (3)] | D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] |
| D.cpp:58:5:58:27 | ... = ... | D.cpp:58:15:58:17 | box [post update] [elem] |
| D.cpp:58:15:58:17 | box [post update] [elem] | D.cpp:58:5:58:12 | boxfield [post update] [box, elem] |
| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] |
| D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] |
| D.cpp:64:10:64:17 | boxfield [box, elem] | D.cpp:64:20:64:22 | box [elem] |
| D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | boxfield [box, elem] |
| D.cpp:64:20:64:22 | box [elem] | D.cpp:64:25:64:28 | elem |
| E.cpp:19:27:19:27 | p [data, buffer] | E.cpp:21:10:21:10 | p [data, buffer] |
| E.cpp:21:10:21:10 | p [data, buffer] | E.cpp:21:13:21:16 | data [buffer] |
| E.cpp:21:13:21:16 | data [buffer] | E.cpp:21:18:21:23 | buffer |
| E.cpp:28:21:28:23 | ref arg raw | E.cpp:31:10:31:12 | raw |
| E.cpp:29:21:29:21 | b [post update] [buffer] | E.cpp:32:10:32:10 | b [buffer] |
| E.cpp:29:24:29:29 | ref arg buffer | E.cpp:29:21:29:21 | b [post update] [buffer] |
| E.cpp:30:21:30:21 | p [post update] [data, buffer] | E.cpp:33:18:33:19 | & ... [data, buffer] |
| E.cpp:30:23:30:26 | data [post update] [buffer] | E.cpp:30:21:30:21 | p [post update] [data, buffer] |
| E.cpp:30:28:30:33 | ref arg buffer | E.cpp:30:23:30:26 | data [post update] [buffer] |
| E.cpp:32:10:32:10 | b [buffer] | E.cpp:32:13:32:18 | buffer |
| E.cpp:33:18:33:19 | & ... [data, buffer] | E.cpp:19:27:19:27 | p [data, buffer] |
| aliasing.cpp:9:3:9:3 | s [post update] [m1] | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] |
| aliasing.cpp:9:3:9:22 | ... = ... | aliasing.cpp:9:3:9:3 | s [post update] [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | ... = ... |
| aliasing.cpp:12:25:12:25 | s [m1] | aliasing.cpp:26:19:26:20 | ref arg s2 [m1] |
| aliasing.cpp:13:3:13:3 | s [post update] [m1] | aliasing.cpp:12:25:12:25 | s [m1] |
| aliasing.cpp:13:3:13:3 | s [post update] [m1] | aliasing.cpp:26:19:26:20 | ref arg s2 [m1] |
| aliasing.cpp:13:3:13:21 | ... = ... | aliasing.cpp:13:3:13:3 | s [post update] [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | ... = ... |
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] | aliasing.cpp:29:8:29:9 | s1 [m1] |
| aliasing.cpp:26:19:26:20 | ref arg s2 [m1] | aliasing.cpp:30:8:30:9 | s2 [m1] |
| aliasing.cpp:29:8:29:9 | s1 [m1] | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:30:8:30:9 | s2 [m1] | aliasing.cpp:30:11:30:12 | m1 |
| aliasing.cpp:60:3:60:4 | s2 [post update] [m1] | aliasing.cpp:62:8:62:12 | copy2 [m1] |
| aliasing.cpp:60:3:60:22 | ... = ... | aliasing.cpp:60:3:60:4 | s2 [post update] [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | ... = ... |
| aliasing.cpp:62:8:62:12 | copy2 [m1] | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | aliasing.cpp:93:8:93:8 | w [s, m1] |
| aliasing.cpp:92:3:92:23 | ... = ... | aliasing.cpp:92:5:92:5 | s [post update] [m1] |
| aliasing.cpp:92:5:92:5 | s [post update] [m1] | aliasing.cpp:92:3:92:3 | w [post update] [s, m1] |
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:92:3:92:23 | ... = ... |
| aliasing.cpp:93:8:93:8 | w [s, m1] | aliasing.cpp:93:10:93:10 | s [m1] |
| aliasing.cpp:93:10:93:10 | s [m1] | aliasing.cpp:93:12:93:13 | m1 |
| by_reference.cpp:50:3:50:3 | ref arg s [a] | by_reference.cpp:51:8:51:8 | s [a] |
| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:3:50:3 | ref arg s [a] |
| by_reference.cpp:51:8:51:8 | s [a] | by_reference.cpp:51:10:51:20 | call to getDirectly |
| by_reference.cpp:56:3:56:3 | ref arg s [a] | by_reference.cpp:57:8:57:8 | s [a] |
| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:56:3:56:3 | ref arg s [a] |
| by_reference.cpp:57:8:57:8 | s [a] | by_reference.cpp:57:10:57:22 | call to getIndirectly |
| by_reference.cpp:62:3:62:3 | ref arg s [a] | by_reference.cpp:63:8:63:8 | s [a] |
| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:62:3:62:3 | ref arg s [a] |
| by_reference.cpp:63:8:63:8 | s [a] | by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
| by_reference.cpp:68:17:68:18 | ref arg & ... [a] | by_reference.cpp:69:22:69:23 | & ... [a] |
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | ref arg & ... [a] |
| by_reference.cpp:69:22:69:23 | & ... [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:102:21:102:39 | ref arg & ... [a] |
| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:103:27:103:35 | ref arg inner_ptr [a] |
| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:106:21:106:41 | ref arg & ... [a] |
| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:107:29:107:37 | ref arg inner_ptr [a] |
| by_reference.cpp:84:3:84:25 | ... = ... | by_reference.cpp:84:3:84:7 | inner [post update] [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | ... = ... |
| by_reference.cpp:87:31:87:35 | inner [a] | by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] |
| by_reference.cpp:87:31:87:35 | inner [a] | by_reference.cpp:123:21:123:36 | ref arg * ... [a] |
| by_reference.cpp:87:31:87:35 | inner [a] | by_reference.cpp:126:29:126:40 | ref arg inner_nested [a] |
| by_reference.cpp:87:31:87:35 | inner [a] | by_reference.cpp:127:21:127:38 | ref arg * ... [a] |
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:87:31:87:35 | inner [a] |
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] |
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:123:21:123:36 | ref arg * ... [a] |
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:126:29:126:40 | ref arg inner_nested [a] |
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:127:21:127:38 | ref arg * ... [a] |
| by_reference.cpp:88:3:88:24 | ... = ... | by_reference.cpp:88:3:88:7 | inner [post update] [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | ... = ... |
| by_reference.cpp:95:25:95:26 | pa | by_reference.cpp:124:21:124:21 | ref arg a |
| by_reference.cpp:95:25:95:26 | pa | by_reference.cpp:128:23:128:23 | ref arg a |
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:95:25:95:26 | pa |
| by_reference.cpp:102:21:102:39 | ref arg & ... [a] | by_reference.cpp:102:28:102:39 | inner_nested [inner post update] [a] |
| by_reference.cpp:102:22:102:26 | outer [post update] [inner_nested, a] | by_reference.cpp:110:8:110:12 | outer [inner_nested, a] |
| by_reference.cpp:102:28:102:39 | inner_nested [inner post update] [a] | by_reference.cpp:102:22:102:26 | outer [post update] [inner_nested, a] |
| by_reference.cpp:103:21:103:25 | outer [post update] [inner_ptr, a] | by_reference.cpp:111:8:111:12 | outer [inner_ptr, a] |
| by_reference.cpp:103:27:103:35 | ref arg inner_ptr [a] | by_reference.cpp:103:21:103:25 | outer [post update] [inner_ptr, a] |
| by_reference.cpp:106:21:106:41 | ref arg & ... [a] | by_reference.cpp:106:30:106:41 | inner_nested [inner post update] [a] |
| by_reference.cpp:106:22:106:27 | pouter [post update] [inner_nested, a] | by_reference.cpp:114:8:114:13 | pouter [inner_nested, a] |
| by_reference.cpp:106:30:106:41 | inner_nested [inner post update] [a] | by_reference.cpp:106:22:106:27 | pouter [post update] [inner_nested, a] |
| by_reference.cpp:107:21:107:26 | pouter [post update] [inner_ptr, a] | by_reference.cpp:115:8:115:13 | pouter [inner_ptr, a] |
| by_reference.cpp:107:29:107:37 | ref arg inner_ptr [a] | by_reference.cpp:107:21:107:26 | pouter [post update] [inner_ptr, a] |
| by_reference.cpp:110:8:110:12 | outer [inner_nested, a] | by_reference.cpp:110:14:110:25 | inner_nested [a] |
| by_reference.cpp:110:14:110:25 | inner_nested [a] | by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:111:8:111:12 | outer [inner_ptr, a] | by_reference.cpp:111:14:111:22 | inner_ptr [a] |
| by_reference.cpp:111:14:111:22 | inner_ptr [a] | by_reference.cpp:111:25:111:25 | a |
| by_reference.cpp:114:8:114:13 | pouter [inner_nested, a] | by_reference.cpp:114:16:114:27 | inner_nested [a] |
| by_reference.cpp:114:16:114:27 | inner_nested [a] | by_reference.cpp:114:29:114:29 | a |
| by_reference.cpp:115:8:115:13 | pouter [inner_ptr, a] | by_reference.cpp:115:16:115:24 | inner_ptr [a] |
| by_reference.cpp:115:16:115:24 | inner_ptr [a] | by_reference.cpp:115:27:115:27 | a |
| by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] | by_reference.cpp:130:8:130:12 | outer [inner_nested, a] |
| by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] | by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] |
| by_reference.cpp:123:21:123:36 | ref arg * ... [a] | by_reference.cpp:123:28:123:36 | inner_ptr [inner post update] [a] |
| by_reference.cpp:123:22:123:26 | outer [post update] [inner_ptr, a] | by_reference.cpp:131:8:131:12 | outer [inner_ptr, a] |
| by_reference.cpp:123:28:123:36 | inner_ptr [inner post update] [a] | by_reference.cpp:123:22:123:26 | outer [post update] [inner_ptr, a] |
| by_reference.cpp:124:15:124:19 | outer [post update] [a] | by_reference.cpp:132:8:132:12 | outer [a] |
| by_reference.cpp:124:21:124:21 | ref arg a | by_reference.cpp:124:15:124:19 | outer [post update] [a] |
| by_reference.cpp:126:21:126:26 | pouter [post update] [inner_nested, a] | by_reference.cpp:134:8:134:13 | pouter [inner_nested, a] |
| by_reference.cpp:126:29:126:40 | ref arg inner_nested [a] | by_reference.cpp:126:21:126:26 | pouter [post update] [inner_nested, a] |
| by_reference.cpp:127:21:127:38 | ref arg * ... [a] | by_reference.cpp:127:30:127:38 | inner_ptr [inner post update] [a] |
| by_reference.cpp:127:22:127:27 | pouter [post update] [inner_ptr, a] | by_reference.cpp:135:8:135:13 | pouter [inner_ptr, a] |
| by_reference.cpp:127:30:127:38 | inner_ptr [inner post update] [a] | by_reference.cpp:127:22:127:27 | pouter [post update] [inner_ptr, a] |
| by_reference.cpp:128:15:128:20 | pouter [post update] [a] | by_reference.cpp:136:8:136:13 | pouter [a] |
| by_reference.cpp:128:23:128:23 | ref arg a | by_reference.cpp:128:15:128:20 | pouter [post update] [a] |
| by_reference.cpp:130:8:130:12 | outer [inner_nested, a] | by_reference.cpp:130:14:130:25 | inner_nested [a] |
| by_reference.cpp:130:14:130:25 | inner_nested [a] | by_reference.cpp:130:27:130:27 | a |
| by_reference.cpp:131:8:131:12 | outer [inner_ptr, a] | by_reference.cpp:131:14:131:22 | inner_ptr [a] |
| by_reference.cpp:131:14:131:22 | inner_ptr [a] | by_reference.cpp:131:25:131:25 | a |
| by_reference.cpp:132:8:132:12 | outer [a] | by_reference.cpp:132:14:132:14 | a |
| by_reference.cpp:134:8:134:13 | pouter [inner_nested, a] | by_reference.cpp:134:16:134:27 | inner_nested [a] |
| by_reference.cpp:134:16:134:27 | inner_nested [a] | by_reference.cpp:134:29:134:29 | a |
| 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 |
| complex.cpp:40:17:40:17 | b [inner, f, ... (3)] | complex.cpp:51:8:51:8 | b [inner, f, ... (3)] |
| complex.cpp:40:17:40:17 | b [inner, f, ... (3)] | complex.cpp:52:8:52:8 | b [inner, f, ... (3)] |
| complex.cpp:51:8:51:8 | b [inner, f, ... (3)] | complex.cpp:51:10:51:14 | inner [f, a_] |
| complex.cpp:51:10:51:14 | inner [f, a_] | complex.cpp:51:16:51:16 | f [a_] |
| complex.cpp:51:16:51:16 | f [a_] | complex.cpp:51:18:51:18 | call to a |
| complex.cpp:52:8:52:8 | b [inner, f, ... (3)] | complex.cpp:52:10:52:14 | inner [f, b_] |
| complex.cpp:52:10:52:14 | inner [f, b_] | complex.cpp:52:16:52:16 | f [b_] |
| complex.cpp:52:16:52:16 | f [b_] | complex.cpp:52:18:52:18 | call to b |
| complex.cpp:62:3:62:4 | b1 [post update] [inner, f, ... (3)] | complex.cpp:68:7:68:8 | b1 [inner, f, ... (3)] |
| complex.cpp:62:6:62:10 | inner [post update] [f, a_] | complex.cpp:62:3:62:4 | b1 [post update] [inner, f, ... (3)] |
| complex.cpp:62:12:62:12 | ref arg f [a_] | complex.cpp:62:6:62:10 | inner [post update] [f, a_] |
| complex.cpp:62:19:62:28 | call to user_input | complex.cpp:62:12:62:12 | ref arg f [a_] |
| complex.cpp:63:3:63:4 | b2 [post update] [inner, f, ... (3)] | complex.cpp:71:7:71:8 | b2 [inner, f, ... (3)] |
| complex.cpp:63:6:63:10 | inner [post update] [f, b_] | complex.cpp:63:3:63:4 | b2 [post update] [inner, f, ... (3)] |
| complex.cpp:63:12:63:12 | ref arg f [b_] | complex.cpp:63:6:63:10 | inner [post update] [f, b_] |
| complex.cpp:63:19:63:28 | call to user_input | complex.cpp:63:12:63:12 | ref arg f [b_] |
| complex.cpp:64:3:64:4 | b3 [post update] [inner, f, ... (3)] | complex.cpp:74:7:74:8 | b3 [inner, f, ... (3)] |
| complex.cpp:64:6:64:10 | inner [post update] [f, a_] | complex.cpp:64:3:64:4 | b3 [post update] [inner, f, ... (3)] |
| complex.cpp:64:12:64:12 | ref arg f [a_] | complex.cpp:64:6:64:10 | inner [post update] [f, a_] |
| complex.cpp:64:19:64:28 | call to user_input | complex.cpp:64:12:64:12 | ref arg f [a_] |
| complex.cpp:65:3:65:4 | b3 [post update] [inner, f, ... (3)] | complex.cpp:74:7:74:8 | b3 [inner, f, ... (3)] |
| complex.cpp:65:6:65:10 | inner [post update] [f, b_] | complex.cpp:65:3:65:4 | b3 [post update] [inner, f, ... (3)] |
| complex.cpp:65:12:65:12 | ref arg f [b_] | complex.cpp:65:6:65:10 | inner [post update] [f, b_] |
| complex.cpp:65:19:65:28 | call to user_input | complex.cpp:65:12:65:12 | ref arg f [b_] |
| complex.cpp:68:7:68:8 | b1 [inner, f, ... (3)] | complex.cpp:40:17:40:17 | b [inner, f, ... (3)] |
| complex.cpp:71:7:71:8 | b2 [inner, f, ... (3)] | complex.cpp:40:17:40:17 | b [inner, f, ... (3)] |
| complex.cpp:74:7:74:8 | b3 [inner, f, ... (3)] | complex.cpp:40:17:40:17 | b [inner, f, ... (3)] |
| constructors.cpp:26:15:26:15 | f [a_] | constructors.cpp:28:10:28:10 | f [a_] |
| constructors.cpp:26:15:26:15 | f [b_] | constructors.cpp:29:10:29:10 | f [b_] |
| constructors.cpp:28:10:28:10 | f [a_] | constructors.cpp:28:12:28:12 | call to a |
| constructors.cpp:29:10:29:10 | f [b_] | constructors.cpp:29:12:29:12 | call to b |
| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:34:11:34:26 | call to Foo [a_] |
| constructors.cpp:34:11:34:26 | call to Foo [a_] | constructors.cpp:40:9:40:9 | f [a_] |
| constructors.cpp:35:11:35:26 | call to Foo [b_] | constructors.cpp:43:9:43:9 | g [b_] |
| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:35:11:35:26 | call to Foo [b_] |
| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:36:11:36:37 | call to Foo [a_] |
| constructors.cpp:36:11:36:37 | call to Foo [a_] | constructors.cpp:46:9:46:9 | h [a_] |
| constructors.cpp:36:11:36:37 | call to Foo [b_] | constructors.cpp:46:9:46:9 | h [b_] |
| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:36:11:36:37 | call to Foo [b_] |
| constructors.cpp:40:9:40:9 | f [a_] | constructors.cpp:26:15:26:15 | f [a_] |
| constructors.cpp:43:9:43:9 | g [b_] | constructors.cpp:26:15:26:15 | f [b_] |
| constructors.cpp:46:9:46:9 | h [a_] | constructors.cpp:26:15:26:15 | f [a_] |
| constructors.cpp:46:9:46:9 | h [b_] | constructors.cpp:26:15:26:15 | f [b_] |
| qualifiers.cpp:22:5:22:9 | ref arg outer [inner, a] | qualifiers.cpp:23:10:23:14 | outer [inner, a] |
| qualifiers.cpp:22:5:22:38 | ... = ... | qualifiers.cpp:22:11:22:18 | call to getInner [post update] [a] |
| qualifiers.cpp:22:11:22:18 | call to getInner [post update] [a] | qualifiers.cpp:22:5:22:9 | ref arg outer [inner, a] |
| qualifiers.cpp:22:27:22:36 | call to user_input | qualifiers.cpp:22:5:22:38 | ... = ... |
| qualifiers.cpp:23:10:23:14 | outer [inner, a] | qualifiers.cpp:23:16:23:20 | inner [a] |
| qualifiers.cpp:23:16:23:20 | inner [a] | qualifiers.cpp:23:23:23:23 | a |
| qualifiers.cpp:27:5:27:9 | ref arg outer [inner, a] | qualifiers.cpp:28:10:28:14 | outer [inner, a] |
| qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] | qualifiers.cpp:27:5:27:9 | ref arg outer [inner, a] |
| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] |
| qualifiers.cpp:28:10:28:14 | outer [inner, a] | qualifiers.cpp:28:16:28:20 | inner [a] |
| qualifiers.cpp:28:16:28:20 | inner [a] | qualifiers.cpp:28:23:28:23 | a |
| qualifiers.cpp:32:17:32:21 | ref arg outer [inner, a] | qualifiers.cpp:33:10:33:14 | outer [inner, a] |
| qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] | qualifiers.cpp:32:17:32:21 | ref arg outer [inner, a] |
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] |
| qualifiers.cpp:33:10:33:14 | outer [inner, a] | qualifiers.cpp:33:16:33:20 | inner [a] |
| qualifiers.cpp:33:16:33:20 | inner [a] | qualifiers.cpp:33:23:33:23 | a |
| qualifiers.cpp:37:19:37:35 | ref arg * ... [a] | qualifiers.cpp:37:26:37:33 | call to getInner [inner post update] [a] |
| qualifiers.cpp:37:20:37:24 | ref arg outer [inner, a] | qualifiers.cpp:38:10:38:14 | outer [inner, a] |
| qualifiers.cpp:37:26:37:33 | call to getInner [inner post update] [a] | qualifiers.cpp:37:20:37:24 | ref arg outer [inner, a] |
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:37:19:37:35 | ref arg * ... [a] |
| qualifiers.cpp:38:10:38:14 | outer [inner, a] | qualifiers.cpp:38:16:38:20 | inner [a] |
| qualifiers.cpp:38:16:38:20 | inner [a] | qualifiers.cpp:38:23:38:23 | a |
| qualifiers.cpp:42:5:42:40 | ... = ... | qualifiers.cpp:42:6:42:22 | * ... [post update] [a] |
| qualifiers.cpp:42:6:42:22 | * ... [post update] [a] | qualifiers.cpp:42:13:42:20 | call to getInner [inner post update] [a] |
| qualifiers.cpp:42:7:42:11 | ref arg outer [inner, a] | qualifiers.cpp:43:10:43:14 | outer [inner, a] |
| qualifiers.cpp:42:13:42:20 | call to getInner [inner post update] [a] | qualifiers.cpp:42:7:42:11 | ref arg outer [inner, a] |
| qualifiers.cpp:42:29:42:38 | call to user_input | qualifiers.cpp:42:5:42:40 | ... = ... |
| qualifiers.cpp:43:10:43:14 | outer [inner, a] | qualifiers.cpp:43:16:43:20 | inner [a] |
| qualifiers.cpp:43:16:43:20 | inner [a] | qualifiers.cpp:43:23:43:23 | a |
| qualifiers.cpp:47:5:47:42 | ... = ... | qualifiers.cpp:47:15:47:22 | call to getInner [post update] [a] |
| qualifiers.cpp:47:6:47:11 | ref arg & ... [inner, a] | qualifiers.cpp:48:10:48:14 | outer [inner, a] |
| qualifiers.cpp:47:15:47:22 | call to getInner [post update] [a] | qualifiers.cpp:47:6:47:11 | ref arg & ... [inner, a] |
| qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:47:5:47:42 | ... = ... |
| qualifiers.cpp:48:10:48:14 | outer [inner, a] | qualifiers.cpp:48:16:48:20 | inner [a] |
| qualifiers.cpp:48:16:48:20 | inner [a] | qualifiers.cpp:48:23:48:23 | a |
| simple.cpp:26:15:26:15 | f [a_] | simple.cpp:28:10:28:10 | f [a_] |
| simple.cpp:26:15:26:15 | f [b_] | simple.cpp:29:10:29:10 | f [b_] |
| simple.cpp:28:10:28:10 | f [a_] | simple.cpp:28:12:28:12 | call to a |
| simple.cpp:29:10:29:10 | f [b_] | simple.cpp:29:12:29:12 | call to b |
| simple.cpp:39:5:39:5 | ref arg f [a_] | simple.cpp:45:9:45:9 | f [a_] |
| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:39:5:39:5 | ref arg f [a_] |
| simple.cpp:40:5:40:5 | ref arg g [b_] | simple.cpp:48:9:48:9 | g [b_] |
| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:40:5:40:5 | ref arg g [b_] |
| simple.cpp:41:5:41:5 | ref arg h [a_] | simple.cpp:51:9:51:9 | h [a_] |
| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:41:5:41:5 | ref arg h [a_] |
| simple.cpp:42:5:42:5 | ref arg h [b_] | simple.cpp:51:9:51:9 | h [b_] |
| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:5:42:5 | ref arg h [b_] |
| simple.cpp:45:9:45:9 | f [a_] | simple.cpp:26:15:26:15 | f [a_] |
| simple.cpp:48:9:48:9 | g [b_] | simple.cpp:26:15:26:15 | f [b_] |
| simple.cpp:51:9:51:9 | h [a_] | simple.cpp:26:15:26:15 | f [a_] |
| simple.cpp:51:9:51:9 | h [b_] | simple.cpp:26:15:26:15 | f [b_] |
| simple.cpp:65:5:65:5 | a [post update] [i] | simple.cpp:67:10:67:11 | a2 [i] |
| simple.cpp:65:5:65:22 | ... = ... | simple.cpp:65:5:65:5 | a [post update] [i] |
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | ... = ... |
| simple.cpp:67:10:67:11 | a2 [i] | simple.cpp:67:13:67:13 | i |
| simple.cpp:83:9:83:10 | f2 [post update] [f1] | simple.cpp:83:9:83:10 | this [post update] [f2, f1] |
| simple.cpp:83:9:83:10 | this [post update] [f2, f1] | simple.cpp:84:14:84:20 | this [f2, f1] |
| simple.cpp:83:9:83:28 | ... = ... | simple.cpp:83:9:83:10 | f2 [post update] [f1] |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | ... = ... |
| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| 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] |
| struct_init.c:20:17:20:36 | {...} [a] | struct_init.c:24:10:24:12 | & ... [a] |
| struct_init.c:20:17:20:36 | {...} [a] | struct_init.c:28:5:28:7 | & ... [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:17:20:36 | {...} [a] |
| struct_init.c:22:8:22:9 | ab [a] | struct_init.c:22:11:22:11 | a |
| struct_init.c:24:10:24:12 | & ... [a] | struct_init.c:14:24:14:25 | ab [a] |
| struct_init.c:26:23:29:3 | {...} [nestedAB, a] | struct_init.c:31:8:31:12 | outer [nestedAB, a] |
| struct_init.c:26:23:29:3 | {...} [nestedAB, a] | struct_init.c:36:11:36:15 | outer [nestedAB, a] |
| struct_init.c:26:23:29:3 | {...} [pointerAB, a] | struct_init.c:33:8:33:12 | outer [pointerAB, a] |
| struct_init.c:27:5:27:23 | {...} [a] | struct_init.c:26:23:29:3 | {...} [nestedAB, a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:5:27:23 | {...} [a] |
| struct_init.c:28:5:28:7 | & ... [a] | struct_init.c:26:23:29:3 | {...} [pointerAB, a] |
| struct_init.c:31:8:31:12 | outer [nestedAB, a] | struct_init.c:31:14:31:21 | nestedAB [a] |
| struct_init.c:31:14:31:21 | nestedAB [a] | struct_init.c:31:23:31:23 | a |
| struct_init.c:33:8:33:12 | outer [pointerAB, a] | struct_init.c:33:14:33:22 | pointerAB [a] |
| struct_init.c:33:14:33:22 | pointerAB [a] | struct_init.c:33:25:33:25 | a |
| struct_init.c:36:10:36:24 | & ... [a] | struct_init.c:14:24:14:25 | ab [a] |
| struct_init.c:36:11:36:15 | outer [nestedAB, a] | struct_init.c:36:17:36:24 | nestedAB [a] |
| struct_init.c:36:17:36:24 | nestedAB [a] | struct_init.c:36:10:36:24 | & ... [a] |
| struct_init.c:40:17:40:36 | {...} [a] | struct_init.c:43:5:43:7 | & ... [a] |
| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:40:17:40:36 | {...} [a] |
| struct_init.c:41:23:44:3 | {...} [pointerAB, a] | struct_init.c:46:10:46:14 | outer [pointerAB, a] |
| struct_init.c:43:5:43:7 | & ... [a] | struct_init.c:41:23:44:3 | {...} [pointerAB, a] |
| struct_init.c:46:10:46:14 | outer [pointerAB, a] | struct_init.c:46:16:46:24 | pointerAB [a] |
| struct_init.c:46:16:46:24 | pointerAB [a] | struct_init.c:14:24:14:25 | ab [a] |
nodes
| A.cpp:41:15:41:21 | new | semmle.label | new |
| A.cpp:43:10:43:12 | & ... | semmle.label | & ... |
| A.cpp:47:12:47:18 | new | semmle.label | new |
| A.cpp:48:12:48:18 | call to make [c] | semmle.label | call to make [c] |
| A.cpp:48:20:48:20 | c | semmle.label | c |
| A.cpp:49:10:49:10 | b [c] | semmle.label | b [c] |
| A.cpp:49:13:49:13 | c | semmle.label | c |
| A.cpp:55:5:55:5 | ref arg b [c] | semmle.label | ref arg b [c] |
| A.cpp:55:12:55:19 | new | semmle.label | new |
| A.cpp:56:10:56:10 | b [c] | semmle.label | b [c] |
| A.cpp:56:13:56:15 | call to get | semmle.label | call to get |
| A.cpp:57:11:57:24 | call to B [c] | semmle.label | call to B [c] |
| A.cpp:57:11:57:24 | new [c] | semmle.label | new [c] |
| 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:64:10:64:15 | call to setOnB [c] | semmle.label | call to setOnB [c] |
| A.cpp:64:21:64:28 | new | semmle.label | new |
| A.cpp:66:10:66:11 | b2 [c] | semmle.label | b2 [c] |
| A.cpp:66:14:66:14 | c | semmle.label | c |
| A.cpp:73:10:73:19 | call to setOnBWrap [c] | semmle.label | call to setOnBWrap [c] |
| A.cpp:73:25:73:32 | new | semmle.label | new |
| A.cpp:75:10:75:11 | b2 [c] | semmle.label | b2 [c] |
| A.cpp:75:14:75:14 | c | semmle.label | c |
| A.cpp:98:12:98:18 | new | semmle.label | new |
| A.cpp:100:5:100:6 | c1 [post update] [a] | semmle.label | c1 [post update] [a] |
| A.cpp:100:5:100:13 | ... = ... | semmle.label | ... = ... |
| A.cpp:101:8:101:9 | c1 [a] | semmle.label | c1 [a] |
| A.cpp:103:14:103:14 | c [a] | semmle.label | c [a] |
| A.cpp:107:12:107:13 | c1 [a] | semmle.label | c1 [a] |
| A.cpp:107:16:107:16 | a | semmle.label | a |
| A.cpp:120:12:120:13 | c1 [a] | semmle.label | c1 [a] |
| A.cpp:120:16:120:16 | a | semmle.label | a |
| A.cpp:126:5:126:5 | ref arg b [c] | semmle.label | ref arg b [c] |
| A.cpp:126:12:126:18 | new | semmle.label | new |
| A.cpp:131:8:131:8 | ref arg b [c] | semmle.label | ref arg b [c] |
| A.cpp:132:10:132:10 | b [c] | semmle.label | b [c] |
| A.cpp:132:13:132:13 | c | semmle.label | c |
| A.cpp:142:7:142:7 | b [post update] [c] | semmle.label | b [post update] [c] |
| A.cpp:142:7:142:20 | ... = ... | semmle.label | ... = ... |
| A.cpp:142:14:142:20 | new | semmle.label | new |
| A.cpp:143:7:143:10 | this [post update] [b, c] | semmle.label | this [post update] [b, c] |
| A.cpp:143:7:143:10 | this [post update] [b] | semmle.label | this [post update] [b] |
| A.cpp:143:7:143:31 | ... = ... | semmle.label | ... = ... |
| A.cpp:143:7:143:31 | ... = ... [c] | semmle.label | ... = ... [c] |
| 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 | call to D [b, c] | semmle.label | call to D [b, c] |
| A.cpp:151:12:151:24 | call to D [b] | semmle.label | call to D [b] |
| A.cpp:151:18:151:18 | b | semmle.label | b |
| A.cpp:151:18:151:18 | ref arg b [c] | semmle.label | ref arg b [c] |
| A.cpp:152:10:152:10 | d [b] | semmle.label | d [b] |
| A.cpp:152:13:152:13 | b | semmle.label | b |
| A.cpp:153:10:153:10 | d [b, c] | semmle.label | d [b, c] |
| A.cpp:153:13:153:13 | b [c] | semmle.label | b [c] |
| A.cpp:153:16:153:16 | c | semmle.label | c |
| A.cpp:154:10:154:10 | b [c] | semmle.label | b [c] |
| A.cpp:154:13:154:13 | c | semmle.label | c |
| A.cpp:159:12:159:18 | new | semmle.label | new |
| A.cpp:160:18:160:60 | call to MyList [head] | semmle.label | call to MyList [head] |
| A.cpp:160:29:160:29 | b | semmle.label | b |
| A.cpp:161:18:161:40 | call to MyList [next, head] | semmle.label | call to MyList [next, head] |
| A.cpp:161:38:161:39 | l1 [head] | semmle.label | l1 [head] |
| A.cpp:162:18:162:40 | call to MyList [next, next, ... (3)] | semmle.label | call to MyList [next, next, ... (3)] |
| A.cpp:162:38:162:39 | l2 [next, head] | semmle.label | l2 [next, head] |
| A.cpp:165:10:165:11 | l3 [next, next, ... (3)] | semmle.label | l3 [next, next, ... (3)] |
| A.cpp:165:14:165:17 | next [next, head] | semmle.label | next [next, head] |
| A.cpp:165:20:165:23 | next [head] | semmle.label | next [head] |
| A.cpp:165:26:165:29 | head | semmle.label | head |
| A.cpp:167:44:167:44 | l [next, head] | semmle.label | l [next, head] |
| A.cpp:167:44:167:44 | l [next, next, ... (3)] | semmle.label | l [next, next, ... (3)] |
| A.cpp:167:47:167:50 | next [head] | semmle.label | next [head] |
| A.cpp:167:47:167:50 | next [next, head] | semmle.label | next [next, head] |
| A.cpp:169:12:169:12 | l [head] | semmle.label | l [head] |
| A.cpp:169:15:169:18 | head | semmle.label | head |
| B.cpp:6:15:6:24 | new | semmle.label | new |
| B.cpp:7:16:7:35 | call to Box1 [elem1] | semmle.label | call to Box1 [elem1] |
| B.cpp:7:25:7:25 | e | semmle.label | e |
| B.cpp:8:16:8:27 | call to Box2 [box1, elem1] | semmle.label | call to Box2 [box1, elem1] |
| B.cpp:8:25:8:26 | b1 [elem1] | semmle.label | b1 [elem1] |
| B.cpp:9:10:9:11 | b2 [box1, elem1] | semmle.label | b2 [box1, elem1] |
| B.cpp:9:14:9:17 | box1 [elem1] | semmle.label | box1 [elem1] |
| B.cpp:9:20:9:24 | elem1 | semmle.label | elem1 |
| B.cpp:15:15:15:27 | new | semmle.label | new |
| B.cpp:16:16:16:38 | call to Box1 [elem2] | semmle.label | call to Box1 [elem2] |
| B.cpp:16:37:16:37 | e | semmle.label | e |
| B.cpp:17:16:17:27 | call to Box2 [box1, elem2] | semmle.label | call to Box2 [box1, elem2] |
| B.cpp:17:25:17:26 | b1 [elem2] | semmle.label | b1 [elem2] |
| B.cpp:19:10:19:11 | b2 [box1, elem2] | semmle.label | b2 [box1, elem2] |
| B.cpp:19:14:19:17 | box1 [elem2] | semmle.label | box1 [elem2] |
| B.cpp:19:20:19:24 | elem2 | semmle.label | elem2 |
| C.cpp:18:12:18:18 | call to C [s1] | semmle.label | call to C [s1] |
| C.cpp:18:12:18:18 | call to C [s3] | semmle.label | call to C [s3] |
| C.cpp:19:5:19:5 | c [s1] | semmle.label | c [s1] |
| C.cpp:19:5:19:5 | c [s3] | semmle.label | c [s3] |
| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | semmle.label | constructor init of field s1 [post-this] [s1] |
| C.cpp:22:12:22:21 | new | semmle.label | new |
| C.cpp:24:5:24:8 | this [post update] [s3] | semmle.label | this [post update] [s3] |
| C.cpp:24:5:24:25 | ... = ... | semmle.label | ... = ... |
| C.cpp:24:16:24:25 | new | semmle.label | new |
| C.cpp:27:8:27:11 | this [s1] | semmle.label | this [s1] |
| C.cpp:27:8:27:11 | this [s3] | semmle.label | this [s3] |
| C.cpp:29:10:29:11 | s1 | semmle.label | s1 |
| C.cpp:29:10:29:11 | this [s1] | semmle.label | this [s1] |
| C.cpp:31:10:31:11 | s3 | semmle.label | s3 |
| C.cpp:31:10:31:11 | this [s3] | semmle.label | this [s3] |
| D.cpp:21:30:21:31 | b2 [box, elem] | semmle.label | b2 [box, elem] |
| D.cpp:22:10:22:11 | b2 [box, elem] | semmle.label | b2 [box, elem] |
| D.cpp:22:14:22:20 | call to getBox1 [elem] | semmle.label | call to getBox1 [elem] |
| D.cpp:22:25:22:31 | call to getElem | semmle.label | call to getElem |
| D.cpp:28:15:28:24 | new | semmle.label | new |
| D.cpp:30:5:30:5 | b [post update] [box, elem] | semmle.label | b [post update] [box, elem] |
| D.cpp:30:5:30:20 | ... = ... | semmle.label | ... = ... |
| D.cpp:30:8:30:10 | box [post update] [elem] | semmle.label | box [post update] [elem] |
| D.cpp:31:14:31:14 | b [box, elem] | semmle.label | b [box, elem] |
| D.cpp:35:15:35:24 | new | semmle.label | new |
| D.cpp:37:5:37:5 | b [post update] [box, elem] | semmle.label | b [post update] [box, elem] |
| D.cpp:37:8:37:10 | ref arg box [elem] | semmle.label | ref arg box [elem] |
| D.cpp:37:21:37:21 | e | semmle.label | e |
| D.cpp:38:14:38:14 | b [box, elem] | semmle.label | b [box, elem] |
| D.cpp:42:15:42:24 | new | semmle.label | new |
| D.cpp:44:5:44:5 | ref arg b [box, elem] | semmle.label | ref arg b [box, elem] |
| D.cpp:44:5:44:26 | ... = ... | semmle.label | ... = ... |
| D.cpp:44:8:44:14 | call to getBox1 [post update] [elem] | semmle.label | call to getBox1 [post update] [elem] |
| D.cpp:45:14:45:14 | b [box, elem] | semmle.label | b [box, elem] |
| D.cpp:49:15:49:24 | new | semmle.label | new |
| D.cpp:51:5:51:5 | ref arg b [box, elem] | semmle.label | ref arg b [box, elem] |
| D.cpp:51:8:51:14 | ref arg call to getBox1 [elem] | semmle.label | ref arg call to getBox1 [elem] |
| D.cpp:51:27:51:27 | e | semmle.label | e |
| D.cpp:52:14:52:14 | b [box, elem] | semmle.label | b [box, elem] |
| D.cpp:56:15:56:24 | new | semmle.label | new |
| D.cpp:58:5:58:12 | boxfield [post update] [box, elem] | semmle.label | boxfield [post update] [box, elem] |
| D.cpp:58:5:58:12 | this [post update] [boxfield, box, ... (3)] | semmle.label | this [post update] [boxfield, box, ... (3)] |
| D.cpp:58:5:58:27 | ... = ... | semmle.label | ... = ... |
| D.cpp:58:15:58:17 | box [post update] [elem] | semmle.label | box [post update] [elem] |
| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
| D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
| D.cpp:64:10:64:17 | boxfield [box, elem] | semmle.label | boxfield [box, elem] |
| D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
| D.cpp:64:20:64:22 | box [elem] | semmle.label | box [elem] |
| D.cpp:64:25:64:28 | elem | semmle.label | elem |
| E.cpp:19:27:19:27 | p [data, buffer] | semmle.label | p [data, buffer] |
| E.cpp:21:10:21:10 | p [data, buffer] | semmle.label | p [data, buffer] |
| E.cpp:21:13:21:16 | data [buffer] | semmle.label | data [buffer] |
| E.cpp:21:18:21:23 | buffer | semmle.label | buffer |
| E.cpp:28:21:28:23 | ref arg raw | semmle.label | ref arg raw |
| E.cpp:29:21:29:21 | b [post update] [buffer] | semmle.label | b [post update] [buffer] |
| E.cpp:29:24:29:29 | ref arg buffer | semmle.label | ref arg buffer |
| E.cpp:30:21:30:21 | p [post update] [data, buffer] | semmle.label | p [post update] [data, buffer] |
| E.cpp:30:23:30:26 | data [post update] [buffer] | semmle.label | data [post update] [buffer] |
| E.cpp:30:28:30:33 | ref arg buffer | semmle.label | ref arg buffer |
| E.cpp:31:10:31:12 | raw | semmle.label | raw |
| E.cpp:32:10:32:10 | b [buffer] | semmle.label | b [buffer] |
| E.cpp:32:13:32:18 | buffer | semmle.label | buffer |
| E.cpp:33:18:33:19 | & ... [data, buffer] | semmle.label | & ... [data, buffer] |
| aliasing.cpp:9:3:9:3 | s [post update] [m1] | semmle.label | s [post update] [m1] |
| aliasing.cpp:9:3:9:22 | ... = ... | semmle.label | ... = ... |
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:12:25:12:25 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:13:3:13:3 | s [post update] [m1] | semmle.label | s [post update] [m1] |
| aliasing.cpp:13:3:13:21 | ... = ... | semmle.label | ... = ... |
| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] | semmle.label | ref arg & ... [m1] |
| aliasing.cpp:26:19:26:20 | ref arg s2 [m1] | semmle.label | ref arg s2 [m1] |
| aliasing.cpp:29:8:29:9 | s1 [m1] | semmle.label | s1 [m1] |
| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 |
| aliasing.cpp:30:8:30:9 | s2 [m1] | semmle.label | s2 [m1] |
| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 |
| aliasing.cpp:60:3:60:4 | s2 [post update] [m1] | semmle.label | s2 [post update] [m1] |
| aliasing.cpp:60:3:60:22 | ... = ... | semmle.label | ... = ... |
| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:62:8:62:12 | copy2 [m1] | semmle.label | copy2 [m1] |
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
| aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | semmle.label | w [post update] [s, m1] |
| aliasing.cpp:92:3:92:23 | ... = ... | semmle.label | ... = ... |
| aliasing.cpp:92:5:92:5 | s [post update] [m1] | semmle.label | s [post update] [m1] |
| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:93:8:93:8 | w [s, m1] | semmle.label | w [s, m1] |
| aliasing.cpp:93:10:93:10 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
| by_reference.cpp:50:3:50:3 | ref arg s [a] | semmle.label | ref arg s [a] |
| by_reference.cpp:50:17:50:26 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:51:8:51:8 | s [a] | semmle.label | s [a] |
| by_reference.cpp:51:10:51:20 | call to getDirectly | semmle.label | call to getDirectly |
| by_reference.cpp:56:3:56:3 | ref arg s [a] | semmle.label | ref arg s [a] |
| by_reference.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:57:8:57:8 | s [a] | semmle.label | s [a] |
| by_reference.cpp:57:10:57:22 | call to getIndirectly | semmle.label | call to getIndirectly |
| by_reference.cpp:62:3:62:3 | ref arg s [a] | semmle.label | ref arg s [a] |
| by_reference.cpp:62:25:62:34 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:63:8:63:8 | s [a] | semmle.label | s [a] |
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | semmle.label | call to getThroughNonMember |
| by_reference.cpp:68:17:68:18 | ref arg & ... [a] | semmle.label | ref arg & ... [a] |
| 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:69:22:69:23 | & ... [a] | semmle.label | & ... [a] |
| by_reference.cpp:84:3:84:7 | inner [post update] [a] | semmle.label | inner [post update] [a] |
| by_reference.cpp:84:3:84:25 | ... = ... | semmle.label | ... = ... |
| by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:87:31:87:35 | inner [a] | semmle.label | inner [a] |
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | semmle.label | inner [post update] [a] |
| by_reference.cpp:88:3:88:24 | ... = ... | semmle.label | ... = ... |
| by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:95:25:95:26 | pa | semmle.label | pa |
| by_reference.cpp:96:8:96:17 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:102:21:102:39 | ref arg & ... [a] | semmle.label | ref arg & ... [a] |
| by_reference.cpp:102:22:102:26 | outer [post update] [inner_nested, a] | semmle.label | outer [post update] [inner_nested, a] |
| by_reference.cpp:102:28:102:39 | inner_nested [inner post update] [a] | semmle.label | inner_nested [inner post update] [a] |
| by_reference.cpp:103:21:103:25 | outer [post update] [inner_ptr, a] | semmle.label | outer [post update] [inner_ptr, a] |
| by_reference.cpp:103:27:103:35 | ref arg inner_ptr [a] | semmle.label | ref arg inner_ptr [a] |
| by_reference.cpp:106:21:106:41 | ref arg & ... [a] | semmle.label | ref arg & ... [a] |
| by_reference.cpp:106:22:106:27 | pouter [post update] [inner_nested, a] | semmle.label | pouter [post update] [inner_nested, a] |
| by_reference.cpp:106:30:106:41 | inner_nested [inner post update] [a] | semmle.label | inner_nested [inner post update] [a] |
| by_reference.cpp:107:21:107:26 | pouter [post update] [inner_ptr, a] | semmle.label | pouter [post update] [inner_ptr, a] |
| by_reference.cpp:107:29:107:37 | ref arg inner_ptr [a] | semmle.label | ref arg inner_ptr [a] |
| by_reference.cpp:110:8:110:12 | outer [inner_nested, a] | semmle.label | outer [inner_nested, a] |
| by_reference.cpp:110:14:110:25 | inner_nested [a] | semmle.label | inner_nested [a] |
| by_reference.cpp:110:27:110:27 | a | semmle.label | a |
| by_reference.cpp:111:8:111:12 | outer [inner_ptr, a] | semmle.label | outer [inner_ptr, a] |
| by_reference.cpp:111:14:111:22 | inner_ptr [a] | semmle.label | inner_ptr [a] |
| by_reference.cpp:111:25:111:25 | a | semmle.label | a |
| by_reference.cpp:114:8:114:13 | pouter [inner_nested, a] | semmle.label | pouter [inner_nested, a] |
| by_reference.cpp:114:16:114:27 | inner_nested [a] | semmle.label | inner_nested [a] |
| by_reference.cpp:114:29:114:29 | a | semmle.label | a |
| by_reference.cpp:115:8:115:13 | pouter [inner_ptr, a] | semmle.label | pouter [inner_ptr, a] |
| by_reference.cpp:115:16:115:24 | inner_ptr [a] | semmle.label | inner_ptr [a] |
| by_reference.cpp:115:27:115:27 | a | semmle.label | a |
| by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] | semmle.label | outer [post update] [inner_nested, a] |
| by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] | semmle.label | ref arg inner_nested [a] |
| by_reference.cpp:123:21:123:36 | ref arg * ... [a] | semmle.label | ref arg * ... [a] |
| by_reference.cpp:123:22:123:26 | outer [post update] [inner_ptr, a] | semmle.label | outer [post update] [inner_ptr, a] |
| by_reference.cpp:123:28:123:36 | inner_ptr [inner post update] [a] | semmle.label | inner_ptr [inner post update] [a] |
| by_reference.cpp:124:15:124:19 | outer [post update] [a] | semmle.label | outer [post update] [a] |
| by_reference.cpp:124:21:124:21 | ref arg a | semmle.label | ref arg a |
| by_reference.cpp:126:21:126:26 | pouter [post update] [inner_nested, a] | semmle.label | pouter [post update] [inner_nested, a] |
| by_reference.cpp:126:29:126:40 | ref arg inner_nested [a] | semmle.label | ref arg inner_nested [a] |
| by_reference.cpp:127:21:127:38 | ref arg * ... [a] | semmle.label | ref arg * ... [a] |
| by_reference.cpp:127:22:127:27 | pouter [post update] [inner_ptr, a] | semmle.label | pouter [post update] [inner_ptr, a] |
| by_reference.cpp:127:30:127:38 | inner_ptr [inner post update] [a] | semmle.label | inner_ptr [inner post update] [a] |
| by_reference.cpp:128:15:128:20 | pouter [post update] [a] | semmle.label | pouter [post update] [a] |
| by_reference.cpp:128:23:128:23 | ref arg a | semmle.label | ref arg a |
| by_reference.cpp:130:8:130:12 | outer [inner_nested, a] | semmle.label | outer [inner_nested, a] |
| by_reference.cpp:130:14:130:25 | inner_nested [a] | semmle.label | inner_nested [a] |
| by_reference.cpp:130:27:130:27 | a | semmle.label | a |
| by_reference.cpp:131:8:131:12 | outer [inner_ptr, a] | semmle.label | outer [inner_ptr, a] |
| by_reference.cpp:131:14:131:22 | inner_ptr [a] | semmle.label | inner_ptr [a] |
| by_reference.cpp:131:25:131:25 | a | semmle.label | a |
| by_reference.cpp:132:8:132:12 | outer [a] | semmle.label | outer [a] |
| by_reference.cpp:132:14:132:14 | a | semmle.label | a |
| by_reference.cpp:134:8:134:13 | pouter [inner_nested, a] | semmle.label | pouter [inner_nested, a] |
| by_reference.cpp:134:16:134:27 | inner_nested [a] | semmle.label | inner_nested [a] |
| by_reference.cpp:134:29:134:29 | a | semmle.label | a |
| by_reference.cpp:135:8:135:13 | pouter [inner_ptr, a] | semmle.label | pouter [inner_ptr, a] |
| by_reference.cpp:135:16:135:24 | inner_ptr [a] | semmle.label | inner_ptr [a] |
| 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 |
| complex.cpp:40:17:40:17 | b [inner, f, ... (3)] | semmle.label | b [inner, f, ... (3)] |
| complex.cpp:51:8:51:8 | b [inner, f, ... (3)] | semmle.label | b [inner, f, ... (3)] |
| complex.cpp:51:10:51:14 | inner [f, a_] | semmle.label | inner [f, a_] |
| complex.cpp:51:16:51:16 | f [a_] | semmle.label | f [a_] |
| complex.cpp:51:18:51:18 | call to a | semmle.label | call to a |
| complex.cpp:52:8:52:8 | b [inner, f, ... (3)] | semmle.label | b [inner, f, ... (3)] |
| complex.cpp:52:10:52:14 | inner [f, b_] | semmle.label | inner [f, b_] |
| complex.cpp:52:16:52:16 | f [b_] | semmle.label | f [b_] |
| complex.cpp:52:18:52:18 | call to b | semmle.label | call to b |
| complex.cpp:62:3:62:4 | b1 [post update] [inner, f, ... (3)] | semmle.label | b1 [post update] [inner, f, ... (3)] |
| complex.cpp:62:6:62:10 | inner [post update] [f, a_] | semmle.label | inner [post update] [f, a_] |
| complex.cpp:62:12:62:12 | ref arg f [a_] | semmle.label | ref arg f [a_] |
| complex.cpp:62:19:62:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:63:3:63:4 | b2 [post update] [inner, f, ... (3)] | semmle.label | b2 [post update] [inner, f, ... (3)] |
| complex.cpp:63:6:63:10 | inner [post update] [f, b_] | semmle.label | inner [post update] [f, b_] |
| complex.cpp:63:12:63:12 | ref arg f [b_] | semmle.label | ref arg f [b_] |
| complex.cpp:63:19:63:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:64:3:64:4 | b3 [post update] [inner, f, ... (3)] | semmle.label | b3 [post update] [inner, f, ... (3)] |
| complex.cpp:64:6:64:10 | inner [post update] [f, a_] | semmle.label | inner [post update] [f, a_] |
| complex.cpp:64:12:64:12 | ref arg f [a_] | semmle.label | ref arg f [a_] |
| complex.cpp:64:19:64:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:65:3:65:4 | b3 [post update] [inner, f, ... (3)] | semmle.label | b3 [post update] [inner, f, ... (3)] |
| complex.cpp:65:6:65:10 | inner [post update] [f, b_] | semmle.label | inner [post update] [f, b_] |
| complex.cpp:65:12:65:12 | ref arg f [b_] | semmle.label | ref arg f [b_] |
| complex.cpp:65:19:65:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:68:7:68:8 | b1 [inner, f, ... (3)] | semmle.label | b1 [inner, f, ... (3)] |
| complex.cpp:71:7:71:8 | b2 [inner, f, ... (3)] | semmle.label | b2 [inner, f, ... (3)] |
| complex.cpp:74:7:74:8 | b3 [inner, f, ... (3)] | semmle.label | b3 [inner, f, ... (3)] |
| constructors.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] |
| constructors.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] |
| constructors.cpp:28:10:28:10 | f [a_] | semmle.label | f [a_] |
| constructors.cpp:28:12:28:12 | call to a | semmle.label | call to a |
| constructors.cpp:29:10:29:10 | f [b_] | semmle.label | f [b_] |
| constructors.cpp:29:12:29:12 | call to b | semmle.label | call to b |
| constructors.cpp:34:11:34:20 | call to user_input | semmle.label | call to user_input |
| constructors.cpp:34:11:34:26 | call to Foo [a_] | semmle.label | call to Foo [a_] |
| constructors.cpp:35:11:35:26 | call to Foo [b_] | semmle.label | call to Foo [b_] |
| constructors.cpp:35:14:35:23 | call to user_input | semmle.label | call to user_input |
| constructors.cpp:36:11:36:20 | call to user_input | semmle.label | call to user_input |
| constructors.cpp:36:11:36:37 | call to Foo [a_] | semmle.label | call to Foo [a_] |
| constructors.cpp:36:11:36:37 | call to Foo [b_] | semmle.label | call to Foo [b_] |
| constructors.cpp:36:25:36:34 | call to user_input | semmle.label | call to user_input |
| constructors.cpp:40:9:40:9 | f [a_] | semmle.label | f [a_] |
| constructors.cpp:43:9:43:9 | g [b_] | semmle.label | g [b_] |
| constructors.cpp:46:9:46:9 | h [a_] | semmle.label | h [a_] |
| constructors.cpp:46:9:46:9 | h [b_] | semmle.label | h [b_] |
| qualifiers.cpp:22:5:22:9 | ref arg outer [inner, a] | semmle.label | ref arg outer [inner, a] |
| qualifiers.cpp:22:5:22:38 | ... = ... | semmle.label | ... = ... |
| qualifiers.cpp:22:11:22:18 | call to getInner [post update] [a] | semmle.label | call to getInner [post update] [a] |
| qualifiers.cpp:22:27:22:36 | call to user_input | semmle.label | call to user_input |
| qualifiers.cpp:23:10:23:14 | outer [inner, a] | semmle.label | outer [inner, a] |
| qualifiers.cpp:23:16:23:20 | inner [a] | semmle.label | inner [a] |
| qualifiers.cpp:23:23:23:23 | a | semmle.label | a |
| qualifiers.cpp:27:5:27:9 | ref arg outer [inner, a] | semmle.label | ref arg outer [inner, a] |
| qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] | semmle.label | ref arg call to getInner [a] |
| qualifiers.cpp:27:28:27:37 | call to user_input | semmle.label | call to user_input |
| qualifiers.cpp:28:10:28:14 | outer [inner, a] | semmle.label | outer [inner, a] |
| qualifiers.cpp:28:16:28:20 | inner [a] | semmle.label | inner [a] |
| qualifiers.cpp:28:23:28:23 | a | semmle.label | a |
| qualifiers.cpp:32:17:32:21 | ref arg outer [inner, a] | semmle.label | ref arg outer [inner, a] |
| qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] | semmle.label | ref arg call to getInner [a] |
| qualifiers.cpp:32:35:32:44 | call to user_input | semmle.label | call to user_input |
| qualifiers.cpp:33:10:33:14 | outer [inner, a] | semmle.label | outer [inner, a] |
| qualifiers.cpp:33:16:33:20 | inner [a] | semmle.label | inner [a] |
| qualifiers.cpp:33:23:33:23 | a | semmle.label | a |
| qualifiers.cpp:37:19:37:35 | ref arg * ... [a] | semmle.label | ref arg * ... [a] |
| qualifiers.cpp:37:20:37:24 | ref arg outer [inner, a] | semmle.label | ref arg outer [inner, a] |
| qualifiers.cpp:37:26:37:33 | call to getInner [inner post update] [a] | semmle.label | call to getInner [inner post update] [a] |
| qualifiers.cpp:37:38:37:47 | call to user_input | semmle.label | call to user_input |
| qualifiers.cpp:38:10:38:14 | outer [inner, a] | semmle.label | outer [inner, a] |
| qualifiers.cpp:38:16:38:20 | inner [a] | semmle.label | inner [a] |
| qualifiers.cpp:38:23:38:23 | a | semmle.label | a |
| qualifiers.cpp:42:5:42:40 | ... = ... | semmle.label | ... = ... |
| qualifiers.cpp:42:6:42:22 | * ... [post update] [a] | semmle.label | * ... [post update] [a] |
| qualifiers.cpp:42:7:42:11 | ref arg outer [inner, a] | semmle.label | ref arg outer [inner, a] |
| qualifiers.cpp:42:13:42:20 | call to getInner [inner post update] [a] | semmle.label | call to getInner [inner post update] [a] |
| qualifiers.cpp:42:29:42:38 | call to user_input | semmle.label | call to user_input |
| qualifiers.cpp:43:10:43:14 | outer [inner, a] | semmle.label | outer [inner, a] |
| qualifiers.cpp:43:16:43:20 | inner [a] | semmle.label | inner [a] |
| qualifiers.cpp:43:23:43:23 | a | semmle.label | a |
| qualifiers.cpp:47:5:47:42 | ... = ... | semmle.label | ... = ... |
| qualifiers.cpp:47:6:47:11 | ref arg & ... [inner, a] | semmle.label | ref arg & ... [inner, a] |
| qualifiers.cpp:47:15:47:22 | call to getInner [post update] [a] | semmle.label | call to getInner [post update] [a] |
| qualifiers.cpp:47:31:47:40 | call to user_input | semmle.label | call to user_input |
| qualifiers.cpp:48:10:48:14 | outer [inner, a] | semmle.label | outer [inner, a] |
| qualifiers.cpp:48:16:48:20 | inner [a] | semmle.label | inner [a] |
| qualifiers.cpp:48:23:48:23 | a | semmle.label | a |
| simple.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] |
| simple.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] |
| simple.cpp:28:10:28:10 | f [a_] | semmle.label | f [a_] |
| simple.cpp:28:12:28:12 | call to a | semmle.label | call to a |
| simple.cpp:29:10:29:10 | f [b_] | semmle.label | f [b_] |
| simple.cpp:29:12:29:12 | call to b | semmle.label | call to b |
| simple.cpp:39:5:39:5 | ref arg f [a_] | semmle.label | ref arg f [a_] |
| simple.cpp:39:12:39:21 | call to user_input | semmle.label | call to user_input |
| simple.cpp:40:5:40:5 | ref arg g [b_] | semmle.label | ref arg g [b_] |
| simple.cpp:40:12:40:21 | call to user_input | semmle.label | call to user_input |
| simple.cpp:41:5:41:5 | ref arg h [a_] | semmle.label | ref arg h [a_] |
| simple.cpp:41:12:41:21 | call to user_input | semmle.label | call to user_input |
| simple.cpp:42:5:42:5 | ref arg h [b_] | semmle.label | ref arg h [b_] |
| simple.cpp:42:12:42:21 | call to user_input | semmle.label | call to user_input |
| simple.cpp:45:9:45:9 | f [a_] | semmle.label | f [a_] |
| simple.cpp:48:9:48:9 | g [b_] | semmle.label | g [b_] |
| simple.cpp:51:9:51:9 | h [a_] | semmle.label | h [a_] |
| simple.cpp:51:9:51:9 | h [b_] | semmle.label | h [b_] |
| simple.cpp:65:5:65:5 | a [post update] [i] | semmle.label | a [post update] [i] |
| simple.cpp:65:5:65:22 | ... = ... | semmle.label | ... = ... |
| simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input |
| simple.cpp:67:10:67:11 | a2 [i] | semmle.label | a2 [i] |
| simple.cpp:67:13:67:13 | i | semmle.label | i |
| simple.cpp:83:9:83:10 | f2 [post update] [f1] | semmle.label | f2 [post update] [f1] |
| simple.cpp:83:9:83:10 | this [post update] [f2, f1] | semmle.label | this [post update] [f2, f1] |
| simple.cpp:83:9:83:28 | ... = ... | semmle.label | ... = ... |
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
| simple.cpp:84:14:84:20 | this [f2, f1] | semmle.label | this [f2, f1] |
| 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 |
| struct_init.c:20:17:20:36 | {...} [a] | semmle.label | {...} [a] |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:22:8:22:9 | ab [a] | semmle.label | ab [a] |
| struct_init.c:22:11:22:11 | a | semmle.label | a |
| struct_init.c:24:10:24:12 | & ... [a] | semmle.label | & ... [a] |
| struct_init.c:26:23:29:3 | {...} [nestedAB, a] | semmle.label | {...} [nestedAB, a] |
| struct_init.c:26:23:29:3 | {...} [pointerAB, a] | semmle.label | {...} [pointerAB, a] |
| struct_init.c:27:5:27:23 | {...} [a] | semmle.label | {...} [a] |
| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input |
| struct_init.c:28:5:28:7 | & ... [a] | semmle.label | & ... [a] |
| struct_init.c:31:8:31:12 | outer [nestedAB, a] | semmle.label | outer [nestedAB, a] |
| struct_init.c:31:14:31:21 | nestedAB [a] | semmle.label | nestedAB [a] |
| struct_init.c:31:23:31:23 | a | semmle.label | a |
| struct_init.c:33:8:33:12 | outer [pointerAB, a] | semmle.label | outer [pointerAB, a] |
| struct_init.c:33:14:33:22 | pointerAB [a] | semmle.label | pointerAB [a] |
| struct_init.c:33:25:33:25 | a | semmle.label | a |
| struct_init.c:36:10:36:24 | & ... [a] | semmle.label | & ... [a] |
| struct_init.c:36:11:36:15 | outer [nestedAB, a] | semmle.label | outer [nestedAB, a] |
| struct_init.c:36:17:36:24 | nestedAB [a] | semmle.label | nestedAB [a] |
| struct_init.c:40:17:40:36 | {...} [a] | semmle.label | {...} [a] |
| struct_init.c:40:20:40:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:41:23:44:3 | {...} [pointerAB, a] | semmle.label | {...} [pointerAB, a] |
| struct_init.c:43:5:43:7 | & ... [a] | semmle.label | & ... [a] |
| struct_init.c:46:10:46:14 | outer [pointerAB, a] | semmle.label | outer [pointerAB, a] |
| struct_init.c:46:16:46:24 | pointerAB [a] | semmle.label | pointerAB [a] |
#select
| A.cpp:43:10:43:12 | & ... | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... | & ... flows from $@ | A.cpp:41:15:41:21 | new | new |
| A.cpp:49:13:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:13:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new |
| A.cpp:56: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 |
| A.cpp:57:28:57:30 | call to get | A.cpp:57:17:57:23 | new | A.cpp:57:28:57:30 | call to get | call to get flows from $@ | A.cpp:57:17:57:23 | new | new |
| A.cpp:66:14:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:14:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new |
| A.cpp:75:14:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:14:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new |
| A.cpp:107:16:107:16 | a | A.cpp:98:12:98:18 | new | A.cpp:107:16:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:120:16:120:16 | a | A.cpp:98:12:98:18 | new | A.cpp:120:16:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new |
| A.cpp:152:13:152:13 | b | A.cpp:143:25:143:31 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new | new |
| A.cpp:152:13:152:13 | b | A.cpp:150:12:150:18 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new | new |
| A.cpp:153:16:153:16 | c | A.cpp:142:14:142:20 | new | A.cpp:153:16:153:16 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:165:26:165:29 | head | A.cpp:159:12:159:18 | new | A.cpp:165:26:165:29 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new |
| A.cpp:169:15:169:18 | head | A.cpp:159:12:159:18 | new | A.cpp:169:15:169:18 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new |
| B.cpp:9:20:9:24 | elem1 | B.cpp:6:15:6:24 | new | B.cpp:9:20:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new | new |
| B.cpp:19:20:19:24 | elem2 | B.cpp:15:15:15:27 | new | B.cpp:19:20:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new | new |
| C.cpp:29:10:29:11 | s1 | C.cpp:22:12:22:21 | new | C.cpp:29:10:29:11 | s1 | s1 flows from $@ | C.cpp:22:12:22:21 | new | new |
| C.cpp:31:10:31:11 | s3 | C.cpp:24:16:24:25 | new | C.cpp:31:10:31:11 | s3 | s3 flows from $@ | C.cpp:24:16:24:25 | new | new |
| D.cpp:22:25:22:31 | call to getElem | D.cpp:28:15:28:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:28:15:28:24 | new | new |
| D.cpp:22:25:22:31 | call to getElem | D.cpp:35:15:35:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:35:15:35:24 | new | new |
| D.cpp:22:25:22:31 | call to getElem | D.cpp:42:15:42:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:42:15:42:24 | new | new |
| D.cpp:22:25:22:31 | call to getElem | D.cpp:49:15:49:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:49:15:49:24 | new | new |
| D.cpp:64:25:64:28 | elem | D.cpp:56:15:56:24 | new | D.cpp:64:25:64:28 | elem | elem flows from $@ | D.cpp:56:15:56:24 | new | new |
| E.cpp:21:18:21:23 | buffer | E.cpp:30:28:30:33 | ref arg buffer | E.cpp:21:18:21:23 | buffer | buffer flows from $@ | E.cpp:30:28:30:33 | ref arg buffer | ref arg buffer |
| E.cpp:31:10:31:12 | raw | E.cpp:28:21:28:23 | ref arg raw | E.cpp:31:10:31:12 | raw | raw flows from $@ | E.cpp:28:21:28:23 | ref arg raw | ref arg raw |
| E.cpp:32:13:32:18 | buffer | E.cpp:29:24:29:29 | ref arg buffer | E.cpp:32:13:32:18 | buffer | buffer flows from $@ | E.cpp:29:24:29:29 | ref arg buffer | ref arg buffer |
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input |
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input |
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input |
| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input |
| by_reference.cpp:51:10:51:20 | call to getDirectly | by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:51:10:51:20 | call to getDirectly | call to getDirectly flows from $@ | by_reference.cpp:50:17:50:26 | call to user_input | call to user_input |
| by_reference.cpp:57:10:57:22 | call to getIndirectly | by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:57:10:57:22 | call to getIndirectly | call to getIndirectly flows from $@ | by_reference.cpp:56:19:56:28 | call to user_input | call to user_input |
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | call to getThroughNonMember flows from $@ | by_reference.cpp:62:25:62:34 | call to user_input | call to user_input |
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | call to nonMemberGetA flows from $@ | by_reference.cpp:68:21:68:30 | call to user_input | call to user_input |
| by_reference.cpp:110:27:110:27 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:110:27:110:27 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
| by_reference.cpp:111:25:111:25 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:111:25:111:25 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
| by_reference.cpp:114:29:114:29 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:114:29:114:29 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
| by_reference.cpp:115:27:115:27 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:115:27:115:27 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
| by_reference.cpp:130:27:130:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:130:27:130:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:131:25:131:25 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:131:25:131:25 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:132:14:132:14 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:132:14:132:14 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input |
| 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 |
| complex.cpp:51:18:51:18 | call to a | complex.cpp:62:19:62:28 | call to user_input | complex.cpp:51:18:51:18 | call to a | call to a flows from $@ | complex.cpp:62:19:62:28 | call to user_input | call to user_input |
| complex.cpp:51:18:51:18 | call to a | complex.cpp:63:19:63:28 | call to user_input | complex.cpp:51:18:51:18 | call to a | call to a flows from $@ | complex.cpp:63:19:63:28 | call to user_input | call to user_input |
| complex.cpp:51:18:51:18 | call to a | complex.cpp:64:19:64:28 | call to user_input | complex.cpp:51:18:51:18 | call to a | call to a flows from $@ | complex.cpp:64:19:64:28 | call to user_input | call to user_input |
| complex.cpp:51:18:51:18 | call to a | complex.cpp:65:19:65:28 | call to user_input | complex.cpp:51:18:51:18 | call to a | call to a flows from $@ | complex.cpp:65:19:65:28 | call to user_input | call to user_input |
| complex.cpp:52:18:52:18 | call to b | complex.cpp:62:19:62:28 | call to user_input | complex.cpp:52:18:52:18 | call to b | call to b flows from $@ | complex.cpp:62:19:62:28 | call to user_input | call to user_input |
| complex.cpp:52:18:52:18 | call to b | complex.cpp:63:19:63:28 | call to user_input | complex.cpp:52:18:52:18 | call to b | call to b flows from $@ | complex.cpp:63:19:63:28 | call to user_input | call to user_input |
| complex.cpp:52:18:52:18 | call to b | complex.cpp:64:19:64:28 | call to user_input | complex.cpp:52:18:52:18 | call to b | call to b flows from $@ | complex.cpp:64:19:64:28 | call to user_input | call to user_input |
| complex.cpp:52:18:52:18 | call to b | complex.cpp:65:19:65:28 | call to user_input | complex.cpp:52:18:52:18 | call to b | call to b flows from $@ | complex.cpp:65:19:65:28 | call to user_input | call to user_input |
| constructors.cpp:28:12:28:12 | call to a | constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:34:11:34:20 | call to user_input | call to user_input |
| constructors.cpp:28:12:28:12 | call to a | constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:36:11:36:20 | call to user_input | call to user_input |
| constructors.cpp:29:12:29:12 | call to b | constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:35:14:35:23 | call to user_input | call to user_input |
| constructors.cpp:29:12:29:12 | call to b | constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:36:25:36:34 | call to user_input | call to user_input |
| qualifiers.cpp:23:23:23:23 | a | qualifiers.cpp:22:27:22:36 | call to user_input | qualifiers.cpp:23:23:23:23 | a | a flows from $@ | qualifiers.cpp:22:27:22:36 | call to user_input | call to user_input |
| qualifiers.cpp:28:23:28:23 | a | qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:28:23:28:23 | a | a flows from $@ | qualifiers.cpp:27:28:27:37 | call to user_input | call to user_input |
| qualifiers.cpp:33:23:33:23 | a | qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:33:23:33:23 | a | a flows from $@ | qualifiers.cpp:32:35:32:44 | call to user_input | call to user_input |
| qualifiers.cpp:38:23:38:23 | a | qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:38:23:38:23 | a | a flows from $@ | qualifiers.cpp:37:38:37:47 | call to user_input | call to user_input |
| qualifiers.cpp:43:23:43:23 | a | qualifiers.cpp:42:29:42:38 | call to user_input | qualifiers.cpp:43:23:43:23 | a | a flows from $@ | qualifiers.cpp:42:29:42:38 | call to user_input | call to user_input |
| qualifiers.cpp:48:23:48:23 | a | qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:48:23:48:23 | a | a flows from $@ | qualifiers.cpp:47:31:47:40 | call to user_input | call to user_input |
| simple.cpp:28:12:28:12 | call to a | simple.cpp:39:12:39:21 | call to user_input | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:39:12:39:21 | call to user_input | call to user_input |
| simple.cpp:28:12:28:12 | call to a | simple.cpp:41:12:41:21 | call to user_input | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:41:12:41:21 | call to user_input | call to user_input |
| simple.cpp:29:12:29:12 | call to b | simple.cpp:40:12:40:21 | call to user_input | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:40:12:40:21 | call to user_input | call to user_input |
| simple.cpp:29:12:29:12 | call to b | simple.cpp:42:12:42:21 | call to user_input | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:42:12:42:21 | call to user_input | call to user_input |
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
| 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 |
| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
| struct_init.c:33:25:33:25 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:33:25:33:25 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |

View File

@@ -0,0 +1,12 @@
/**
* @kind path-problem
*/
import semmle.code.cpp.dataflow.DataFlow
import ASTConfiguration
import cpp
import DataFlow::PathGraph
from DataFlow::PathNode src, DataFlow::PathNode sink, Conf conf
where conf.hasFlowPath(src, sink)
select sink, src, sink, sink + " flows from $@", src, src.toString()

View File

@@ -81,7 +81,7 @@ struct C2
void m() {
f2.f1 = user_input();
sink(getf2f1()); //$ast $f-:ir
sink(getf2f1()); //$ast,ir
}
};

View File

@@ -12,7 +12,7 @@ struct Outer {
};
void absink(struct AB *ab) {
sink(ab->a); //$ast=20:20 $ast=27:7 $ast=40:20 $f-:ir
sink(ab->a); //$ast,ir=20:20 $ast,ir=27:7 $ast=40:20 $f-:ir
sink(ab->b); // no flow
}

View File

@@ -23,14 +23,9 @@
| taint.cpp:130:7:130:9 | taint.cpp:127:8:127:13 | IR only |
| taint.cpp:137:7:137:9 | taint.cpp:120:11:120:16 | AST only |
| taint.cpp:173:8:173:13 | taint.cpp:164:19:164:24 | AST only |
| taint.cpp:181:8:181:9 | taint.cpp:185:11:185:16 | AST only |
| taint.cpp:195:7:195:7 | taint.cpp:192:23:192:28 | AST only |
| taint.cpp:195:7:195:7 | taint.cpp:193:6:193:6 | AST only |
| taint.cpp:229:3:229:6 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:233:8:233:8 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:236:3:236:6 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:244:3:244:6 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:256:8:256:8 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:261:7:261:7 | taint.cpp:258:7:258:12 | AST only |
| taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only |
| taint.cpp:352:7:352:7 | taint.cpp:330:6:330:11 | AST only |

View File

@@ -21,10 +21,15 @@
| taint.cpp:151:7:151:12 | call to select | taint.cpp:151:20:151:25 | call to source |
| taint.cpp:167:8:167:13 | call to source | taint.cpp:167:8:167:13 | call to source |
| taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source |
| taint.cpp:181:8:181:9 | * ... | taint.cpp:185:11:185:16 | call to source |
| taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source |
| taint.cpp:215:7:215:7 | x | taint.cpp:207:6:207:11 | call to source |
| taint.cpp:216:7:216:7 | y | taint.cpp:207:6:207:11 | call to source |
| taint.cpp:229:3:229:6 | t | taint.cpp:223:10:223:15 | call to source |
| taint.cpp:233:8:233:8 | call to operator() | taint.cpp:223:10:223:15 | call to source |
| taint.cpp:244:3:244:6 | t | taint.cpp:223:10:223:15 | call to source |
| taint.cpp:250:8:250:8 | a | taint.cpp:223:10:223:15 | call to source |
| taint.cpp:256:8:256:8 | (reference dereference) | taint.cpp:223:10:223:15 | call to source |
| taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:290:7:290:7 | x | taint.cpp:275:6:275:11 | call to source |

View File

@@ -10483,6 +10483,35 @@ ir.cpp:
# 1315| 2: [VariableAccess] y
# 1315| Type = [IntType] int
# 1315| ValueCategory = prvalue(load)
# 1318| [Operator,TopLevelFunction] void* operator new(size_t, void*)
# 1318| params:
# 1318| 0: [Parameter] p#0
# 1318| Type = [CTypedefType,Size_t] size_t
# 1318| 1: [Parameter] p#1
# 1318| Type = [VoidPointerType] void *
# 1320| [TopLevelFunction] void f(int*)
# 1320| params:
# 1320| 0: [Parameter] p
# 1320| Type = [IntPointerType] int *
# 1321| body: [Block] { ... }
# 1322| 0: [ExprStmt] ExprStmt
# 1322| 0: [NewExpr] new
# 1322| Type = [IntPointerType] int *
# 1322| ValueCategory = prvalue
# 1322| 0: [FunctionCall] call to operator new
# 1322| Type = [VoidPointerType] void *
# 1322| ValueCategory = prvalue
# 1322| 0: [ErrorExpr] <error expr>
# 1322| Type = [LongType] unsigned long
# 1322| ValueCategory = prvalue
# 1322| 1: [CStyleCast] (void *)...
# 1322| Conversion = [PointerConversion] pointer conversion
# 1322| Type = [VoidPointerType] void *
# 1322| ValueCategory = prvalue
# 1322| expr: [VariableAccess] p
# 1322| Type = [IntPointerType] int *
# 1322| ValueCategory = prvalue(load)
# 1323| 1: [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| params:

View File

@@ -1315,4 +1315,11 @@ int shortCircuitConditional(int x, int y) {
return predicateA() && predicateB() ? x : y;
}
void *operator new(size_t, void *) noexcept;
void f(int* p)
{
new (p) int;
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -7409,6 +7409,30 @@ ir.cpp:
# 1314| v1314_10(void) = AliasedUse : ~m?
# 1314| v1314_11(void) = ExitFunction :
# 1320| void f(int*)
# 1320| Block 0
# 1320| v1320_1(void) = EnterFunction :
# 1320| mu1320_2(unknown) = AliasedDefinition :
# 1320| mu1320_3(unknown) = InitializeNonLocal :
# 1320| r1320_4(glval<int *>) = VariableAddress[p] :
# 1320| mu1320_5(int *) = InitializeParameter[p] : &:r1320_4
# 1320| r1320_6(int *) = Load : &:r1320_4, ~m?
# 1320| mu1320_7(unknown) = InitializeIndirection[p] : &:r1320_6
# 1322| r1322_1(glval<unknown>) = FunctionAddress[operator new] :
# 1322| r1322_2(unsigned long) = Constant[4] :
# 1322| r1322_3(glval<int *>) = VariableAddress[p] :
# 1322| r1322_4(int *) = Load : &:r1322_3, ~m?
# 1322| r1322_5(void *) = Convert : r1322_4
# 1322| r1322_6(void *) = Call : func:r1322_1, 0:r1322_2, 1:r1322_5
# 1322| mu1322_7(unknown) = ^CallSideEffect : ~m?
# 1322| mu1322_8(unknown) = ^InitializeDynamicAllocation : &:r1322_6
# 1322| r1322_9(int *) = Convert : r1322_6
# 1323| v1323_1(void) = NoOp :
# 1320| v1320_8(void) = ReturnIndirection[p] : &:r1320_6, ~m?
# 1320| v1320_9(void) = ReturnVoid :
# 1320| v1320_10(void) = AliasedUse : ~m?
# 1320| v1320_11(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -39,7 +39,6 @@ instructionWithoutSuccessor
| condition_decls.cpp:26:23:26:24 | Chi: call to BoxedInt |
| condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt |
| condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt |
| cpp17.cpp:15:11:15:21 | Convert: (void *)... |
| misc.c:171:10:171:13 | Uninitialized: definition of str2 |
| misc.c:219:47:219:48 | InitializeIndirection: sp |
| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x |
@@ -156,8 +155,6 @@ ambiguousSuccessors
| constructorinitializer.cpp:6:6:6:6 | Chi: f | Goto | 14 | pmcallexpr.cpp:7:5:7:5 | VariableAddress: definition of c |
| constructorinitializer.cpp:6:6:6:6 | Chi: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
| constructorinitializer.cpp:6:6:6:6 | Chi: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i |
| cpp17.cpp:15:19:15:21 | Load: ptr | Goto | 2 | cpp17.cpp:15:5:15:45 | Call: new |
| cpp17.cpp:15:19:15:21 | Load: ptr | Goto | 2 | cpp17.cpp:15:11:15:21 | Convert: (void *)... |
| defconstructornewexpr.cpp:3:6:3:6 | Chi: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... |
| defconstructornewexpr.cpp:3:6:3:6 | Chi: f | Goto | 14 | assignexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
| defconstructornewexpr.cpp:3:6:3:6 | Chi: f | Goto | 14 | constmemberaccess.cpp:7:5:7:5 | VariableAddress: definition of c |

View File

@@ -200,7 +200,7 @@ uniqueNodeLocation
| fieldaccess.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. |
| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. |
| fieldaccess.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. |
| file://:0:0:0:0 | InitializeIndirection | Node should have one location but has 0. |
| file://:0:0:0:0 | *p#2 | Node should have one location but has 0. |
| file://:0:0:0:0 | Load | Node should have one location but has 0. |
| file://:0:0:0:0 | ReturnIndirection | Node should have one location but has 0. |
| file://:0:0:0:0 | VariableAddress | Node should have one location but has 0. |

View File

@@ -52,7 +52,6 @@ instructionWithoutSuccessor
| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt |
| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt |
| cpp17.cpp:15:5:15:45 | InitializeDynamicAllocation: new |
| cpp17.cpp:15:11:15:21 | Convert: (void *)... |
| enum.c:6:9:6:9 | Constant: (int)... |
| file://:0:0:0:0 | CompareNE: (bool)... |
| file://:0:0:0:0 | CompareNE: (bool)... |
@@ -208,8 +207,6 @@ ambiguousSuccessors
| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal: f | Goto | 14 | pmcallexpr.cpp:7:5:7:5 | VariableAddress: definition of c |
| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i |
| cpp17.cpp:15:19:15:21 | Load: ptr | Goto | 2 | cpp17.cpp:15:5:15:45 | Call: new |
| cpp17.cpp:15:19:15:21 | Load: ptr | Goto | 2 | cpp17.cpp:15:11:15:21 | Convert: (void *)... |
| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... |
| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Goto | 14 | assignexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Goto | 14 | constmemberaccess.cpp:7:5:7:5 | VariableAddress: definition of c |

View File

@@ -39,7 +39,6 @@ instructionWithoutSuccessor
| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt |
| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt |
| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt |
| cpp17.cpp:15:11:15:21 | Convert: (void *)... |
| misc.c:171:10:171:13 | Uninitialized: definition of str2 |
| misc.c:219:47:219:48 | InitializeIndirection: sp |
| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x |
@@ -156,8 +155,6 @@ ambiguousSuccessors
| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal: f | Goto | 14 | pmcallexpr.cpp:7:5:7:5 | VariableAddress: definition of c |
| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i |
| cpp17.cpp:15:19:15:21 | Load: ptr | Goto | 2 | cpp17.cpp:15:5:15:45 | Call: new |
| cpp17.cpp:15:19:15:21 | Load: ptr | Goto | 2 | cpp17.cpp:15:11:15:21 | Convert: (void *)... |
| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... |
| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Goto | 14 | assignexpr.cpp:7:4:7:4 | VariableAddress: definition of c |
| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Goto | 14 | constmemberaccess.cpp:7:5:7:5 | VariableAddress: definition of c |

View File

@@ -53,6 +53,8 @@ edges
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | Argument 0 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | Argument 0 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion |
@@ -63,6 +65,8 @@ edges
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | Argument 0 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | Argument 0 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 |
@@ -77,9 +81,11 @@ edges
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:117:15:117:16 | Argument 0 indirection | argvLocal.c:117:15:117:16 | printWrapper output argument |
| argvLocal.c:117:15:117:16 | array to pointer conversion | argvLocal.c:117:15:117:16 | printWrapper output argument |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | (const char *)... |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | Argument 0 indirection |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 |
@@ -87,6 +93,7 @@ edges
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... |
| argvLocal.c:122:15:122:16 | Argument 0 indirection | argvLocal.c:122:15:122:16 | printWrapper output argument |
| argvLocal.c:122:15:122:16 | i4 | argvLocal.c:122:15:122:16 | printWrapper output argument |
| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | (const char *)... |
| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ |
@@ -96,6 +103,8 @@ edges
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | (const char *)... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | Argument 0 indirection |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | Argument 0 indirection |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion |
@@ -110,6 +119,7 @@ edges
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... |
| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... |
| argvLocal.c:128:15:128:16 | Argument 0 indirection | argvLocal.c:128:15:128:16 | printWrapper output argument |
| argvLocal.c:128:15:128:16 | array to pointer conversion | argvLocal.c:128:15:128:16 | printWrapper output argument |
| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | (const char *)... |
| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | ... + ... |
@@ -156,8 +166,10 @@ edges
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 |
nodes
| argvLocal.c:9:25:9:31 | *correct | semmle.label | *correct |
| argvLocal.c:9:25:9:31 | correct | semmle.label | correct |
| argvLocal.c:10:9:10:15 | Chi | semmle.label | Chi |
| argvLocal.c:10:9:10:15 | Chi | semmle.label | Chi |
| argvLocal.c:95:9:95:12 | argv | semmle.label | argv |
| argvLocal.c:95:9:95:12 | argv | semmle.label | argv |
| argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... |
@@ -203,6 +215,7 @@ nodes
| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 |
| argvLocal.c:117:15:117:16 | Argument 0 indirection | semmle.label | Argument 0 indirection |
| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion |
| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion |
| argvLocal.c:117:15:117:16 | i3 | semmle.label | i3 |
@@ -210,6 +223,7 @@ nodes
| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 |
| argvLocal.c:122:15:122:16 | Argument 0 indirection | semmle.label | Argument 0 indirection |
| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |
| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |
| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 |
@@ -219,6 +233,7 @@ nodes
| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... |
| argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 |
| argvLocal.c:128:15:128:16 | Argument 0 indirection | semmle.label | Argument 0 indirection |
| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion |
| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion |
| argvLocal.c:128:15:128:16 | i5 | semmle.label | i5 |

View File

@@ -35,11 +35,5 @@ import semmle.code.csharp.dataflow.DataFlow
import semmle.code.csharp.dataflow.TaintTracking
import semmle.code.csharp.dataflow.SSA
/** DEPRECATED: Use `ControlFlow` instead. */
deprecated module ControlFlowGraph {
import semmle.code.csharp.controlflow.ControlFlowGraph
import ControlFlow
}
/** Whether the source was extracted without a build command. */
predicate extractionIsStandalone() { exists(SourceFile f | f.extractedStandalone()) }

View File

@@ -25,12 +25,6 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
/** Gets the annotated return type of this callable. */
final AnnotatedType getAnnotatedReturnType() { result.appliesTo(this) }
/** DEPRECATED: Use `getAnnotatedReturnType().isRef()` instead. */
deprecated predicate returnsRef() { this.getAnnotatedReturnType().isRef() }
/** DEPRECATED: Use `getAnnotatedReturnType().isReadonlyRef()` instead. */
deprecated predicate returnsRefReadonly() { this.getAnnotatedReturnType().isReadonlyRef() }
override Callable getSourceDeclaration() { result = Parameterizable.super.getSourceDeclaration() }
/**

View File

@@ -197,24 +197,6 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
* ```
*/
class TypeParameterConstraints extends Element, @type_parameter_constraints {
/**
* DEPRECATED: Use `getATypeConstraint()` instead.
* Gets a specific interface constraint, if any.
*/
deprecated Interface getAnInterfaceConstraint() { result = getATypeConstraint() }
/**
* DEPRECATED: Use `getATypeConstraint()` instead.
* Gets a specific type parameter constraint, if any.
*/
deprecated TypeParameter getATypeParameterConstraint() { result = getATypeConstraint() }
/**
* DEPRECATED: Use `getATypeConstraint()` instead.
* Gets the specific class constraint, if any.
*/
deprecated Class getClassConstraint() { result = getATypeConstraint() }
/** Gets a specific type constraint, if any. */
Type getATypeConstraint() { specific_type_parameter_constraints(this, getTypeRef(result)) }

View File

@@ -178,9 +178,6 @@ class SwitchStmt extends SelectionStmt, Switch, @switch_stmt {
/** Gets the default case of this `switch` statement, if any. */
DefaultCase getDefaultCase() { result = this.getACase() }
/** Gets a type case of this `switch` statement, if any. */
deprecated TypeCase getATypeCase() { result = this.getACase() }
override string toString() { result = "switch (...) {...}" }
/**
@@ -310,73 +307,6 @@ class ConstCase extends CaseStmt, LabeledStmt {
override string toString() { result = CaseStmt.super.toString() }
}
/**
* A type matching case in a `switch` statement, for example `case int i:` on line 3 or
* `case string s when s.Length > 0:` on line 4 in
*
* ```
* switch(p)
* {
* case int i:
* case string s when s.Length > 0:
* break;
* ...
* }
* ```
*/
deprecated class TypeCase extends CaseStmt {
private TypeAccess ta;
TypeCase() { expr_parent(ta, 1, this) }
/**
* Gets the local variable declaration of this type case, if any. For example,
* the local variable declaration of the type case on line 3 is `string s` in
*
* ```
* switch(p) {
* case int i:
* case string s when s.Length>0:
* break;
* case bool _:
* break;
* ...
* }
* ```
*/
LocalVariableDeclExpr getVariableDeclExpr() { result = this.getPattern() }
/**
* Gets the type access of this case, for example access to `string` or
* access to `int` in
*
* ```
* switch(p) {
* case int i:
* case string s when s.Length>0:
* break;
* ...
* }
* ```
*/
TypeAccess getTypeAccess() { result = ta }
/**
* Gets the type being checked by this case. For example, the type being checked
* by the type case on line 3 is `string` in
*
* ```
* switch(p) {
* case int i:
* case string s when s.Length>0:
* break;
* ...
* }
* ```
*/
Type getCheckedType() { result = this.getTypeAccess().getType() }
}
/**
* A default case of a `switch` statement, for example `default:` on
* line 3 in

View File

@@ -769,12 +769,6 @@ class DelegateType extends RefType, Parameterizable, @delegate_type {
/** Gets the annotated return type of this delegate. */
AnnotatedType getAnnotatedReturnType() { result.appliesTo(this) }
/** Holds if this delegate returns a `ref`. */
deprecated predicate returnsRef() { this.getAnnotatedReturnType().isRef() }
/** Holds if this delegate returns a `ref readonly`. */
deprecated predicate returnsRefReadonly() { this.getAnnotatedReturnType().isReadonlyRef() }
}
/**

View File

@@ -1,6 +1,4 @@
/**
* DEPRECATED.
*
* Provides classes representing data flow sources for parameters of public callables.
*/

View File

@@ -441,65 +441,6 @@ class IsExpr extends Expr, PatternMatch, @is_expr {
override string toString() { result = "... is ..." }
}
/** An `is` type expression, for example, `x is string` or `x is string s`. */
deprecated class IsTypeExpr extends IsExpr {
TypeAccess typeAccess;
IsTypeExpr() { typeAccess = this.getChild(1) }
/**
* Gets the type being accessed in this `is` expression, for example `string`
* in `x is string`.
*/
Type getCheckedType() { result = typeAccess.getTarget() }
/**
* Gets the type access in this `is` expression, for example `string` in
* `x is string`.
*/
TypeAccess getTypeAccess() { result = typeAccess }
}
/** An `is` pattern expression, for example `x is string s`. */
deprecated class IsPatternExpr extends IsExpr {
LocalVariableDeclExpr typeDecl;
IsPatternExpr() { typeDecl = this.getChild(2) }
/**
* Gets the local variable declaration in this `is` pattern expression.
* For example `string s` in `x is string s`.
*/
LocalVariableDeclExpr getVariableDeclExpr() { result = typeDecl }
/**
* Gets the type being accessed in this `is` expression, for example `string`
* in `x is string`.
*/
Type getCheckedType() { result = getTypeAccess().getTarget() }
/**
* Gets the type access in this `is` expression, for example `string` in
* `x is string`.
*/
TypeAccess getTypeAccess() { result = this.getChild(1) }
}
/**
* An `is` constant expression, for example `x is 5`.
*/
deprecated class IsConstantExpr extends IsExpr {
ConstantPatternExpr constant;
IsConstantExpr() { constant = this.getPattern() }
/** Gets the constant expression, for example `5` in `x is 5`. */
Expr getConstant() { result = constant }
/** Gets the value of the constant, for example 5 in `x is 5`. */
string getConstantValue() { result = constant.getValue() }
}
/** A `switch` expression or statement. */
class Switch extends ControlFlowElement, @switch {
/** Gets the `i`th case of this `switch`. */

View File

@@ -56,7 +56,7 @@ class ValueNumber extends TValueNumber {
or
this instanceof TInitializeParameterValueNumber and result = "InitializeParameter"
or
this instanceof TInitializeThisValueNumber and result = "InitializeThis"
this instanceof TConstantValueNumber and result = "Constant"
or
this instanceof TStringConstantValueNumber and result = "StringConstant"
or

View File

@@ -7,7 +7,6 @@ newtype TValueNumber =
TInitializeParameterValueNumber(IRFunction irFunc, Language::AST var) {
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
@@ -79,8 +78,6 @@ private predicate numberableInstruction(Instruction instr) {
or
instr instanceof InitializeParameterInstruction
or
instr instanceof InitializeThisInstruction
or
instr instanceof ConstantInstruction
or
instr instanceof StringConstantInstruction
@@ -132,10 +129,6 @@ private predicate initializeParameterValueNumber(
instr.getIRVariable().getAST() = var
}
private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc
}
private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
@@ -268,9 +261,6 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
result = TInitializeParameterValueNumber(irFunc, var)
)
or
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(string value, IRType type |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)

View File

@@ -56,7 +56,7 @@ class ValueNumber extends TValueNumber {
or
this instanceof TInitializeParameterValueNumber and result = "InitializeParameter"
or
this instanceof TInitializeThisValueNumber and result = "InitializeThis"
this instanceof TConstantValueNumber and result = "Constant"
or
this instanceof TStringConstantValueNumber and result = "StringConstant"
or

View File

@@ -7,7 +7,6 @@ newtype TValueNumber =
TInitializeParameterValueNumber(IRFunction irFunc, Language::AST var) {
initializeParameterValueNumber(_, irFunc, var)
} or
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
constantValueNumber(_, irFunc, type, value)
} or
@@ -79,8 +78,6 @@ private predicate numberableInstruction(Instruction instr) {
or
instr instanceof InitializeParameterInstruction
or
instr instanceof InitializeThisInstruction
or
instr instanceof ConstantInstruction
or
instr instanceof StringConstantInstruction
@@ -132,10 +129,6 @@ private predicate initializeParameterValueNumber(
instr.getIRVariable().getAST() = var
}
private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) {
instr.getEnclosingIRFunction() = irFunc
}
private predicate constantValueNumber(
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
) {
@@ -268,9 +261,6 @@ private TValueNumber nonUniqueValueNumber(Instruction instr) {
result = TInitializeParameterValueNumber(irFunc, var)
)
or
initializeThisValueNumber(instr, irFunc) and
result = TInitializeThisValueNumber(irFunc)
or
exists(string value, IRType type |
constantValueNumber(instr, irFunc, type, value) and
result = TConstantValueNumber(irFunc, type, value)

View File

@@ -42,6 +42,8 @@ of ``OldVersion``, you could deprecate the name ``OldVersion`` as follows::
That way both names resolve to the same module, but if you use the name ``OldVersion``,
a deprecation warning is displayed.
.. _type-aliases:
Type aliases
============

View File

@@ -42,6 +42,76 @@ A QL program can be *evaluated* (see `Evaluation <#evaluation>`__) to produce a
For a QL program to be *valid*, it must conform to a variety of conditions that are described throughout this specification; otherwise the program is said to be *invalid*. An implementation of QL must detect all invalid programs and refuse to evaluate them.
Library path
------------
The library path is an ordered list of directory locations. It is used
for resolving module imports (see `Module resolution <#module-resolution>`__). The library path is not strictly
speaking a core part of the QL language, since different
implementations of QL construct it in slightly different ways. Most QL
tools also allow you to explicitly specify the library path on the command line for a
particular invocation, though that is rarely done, and only
useful in very special situations. This section describes the default
construction of the library path.
First, determine the *query directory* of the ``.ql`` file being
compiled. Starting with the directory containing the ``.ql`` file, and
walking up the directory structure, each directory is checked for a
file called ``queries.xml`` or ``qlpack.yml``. The first directory
where such a file is found is the query directory. If there is no such
directory, the directory of the ``.ql`` file itself is the query
directory.
A ``queries.xml`` file that defines a query directory must always
contain a single top-level tag named
``queries``, which has a ``language`` attribute set to the identifier
of the active database schema (for example, ``<queries
language="java"/>``).
A ``qlpack.yml`` file defines a `QL pack
<https://help.semmle.com/codeql/codeql-cli/reference/qlpack-overview.html>`__.
The content of a ``qlpack.yml`` file is described in the CodeQL CLI documentation. This file
will not be recognized when using legacy tools that are not based
on the CodeQL CLI (that is, LGTM.com, LGTM Enterprise, ODASA, CodeQL for
Eclipse, and CodeQL for Visual Studio).
If both a ``queries.xml`` and a ``qlpack.yml`` exist in the same
directory, the latter takes precedence (and the former is assumed to
exist for compatibility with older tooling).
In legacy QL tools that don't recognize ``qlpack.yml`` files, the default
value of the library path for
each supported language is hard-coded. The tools contain directories within the ODASA
distribution that define the default CodeQL libraries for the selected
language. Which language to use depends on the ``language`` attribute
of the ``queries.xml`` file if not overridden with a ``--language``
option to the ODASA CLI.
On the other hand, the CodeQL CLI and newer tools based on it (such as
GitHub Code Scanning and the CodeQL extension for Visual Studio Code)
construct a library path using QL packs. For each QL pack
added to the library path, the QL packs named in its
``libraryPathDependencies`` will be subsequently added to the library
path, and the process continues until all packs have been
resolved. The actual library path consists of the root directories of
the selected QL packs. This process depends on a mechanism for finding
QL packs by pack name, as described in the `CodeQL CLI documentation <https://help.semmle.com/codeql/codeql-cli.html>`__.
When the query directory contains a ``queries.xml`` file but no
``qlpack.yml``, the QL pack resolution behaves as if it defines a QL
pack with no name and a single library path dependency named
``legacy-libraries-LANGUAGE`` where ``LANGUAGE`` is taken from
``queries.xml``. The ``github/codeql`` repository provides packs with
names following this pattern, which themselves depend on the actual
CodeQL libraries for each language.
When the query directory contains neither a ``queries.xml`` nor
``qlpack.yml`` file, it is considered to be a QL pack with no name and
no library dependencies. This causes the library path to consist of
*only* the query directory itself. This is not generally useful,
but it suffices for running toy examples of QL code that don't
use information from the database.
Name resolution
---------------
@@ -162,11 +232,10 @@ For selection identifiers (``a::b``):
For qualified identifiers (``a.b``):
- Define the *current file* as the file the import directive occurs in.
- Determine the current file's *query directory*, if any. Starting with the directory containing the current file, and walking up the directory structure, each directory is checked for a file called ``queries.xml``, containing a single top-level tag named ``queries``, which has a ``language`` attribute set to the identifier of the active database scheme (for example, ``<queries language="java"/>``). The closest enclosing directory is taken as the current file's query directory.
- Build up a list of *candidate search paths*, consisting of the current file's directory, the current file's query directory (if one was determined in the previous step), and the list of directories making up the library path (in order).
- Build up a list of *candidate search paths*, consisting of the
current file's directory, then the *query directory* of the current
file, and finally each of the directories on the
`library path <#library-path>`__ (in order).
- Determine the first candidate search path that has a *matching* QLL file for the import directive's qualified name. A QLL file in a candidate search path is said to match a qualified name if, starting from the candidate search path, there is a subdirectory for each successive qualifier in the qualified name, and the directory named by the final qualifier contains a file whose base name matches the qualified name's base name, with the addition of the file extension ``.qll``. The file and directory names are matched case-sensitively, regardless of whether the filesystem is case-sensitive or not.

View File

@@ -14,7 +14,8 @@ than one type.
The kinds of types in QL are :ref:`primitive types <primitive-types>`, :ref:`classes <classes>`,
:ref:`character types <character-types>`, :ref:`class domain types <domain-types>`,
:ref:`algebraic datatypes <algebraic-datatypes>`, and :ref:`database types <database-types>`.
:ref:`algebraic datatypes <algebraic-datatypes>`, :ref:`type unions <type-unions>`,
and :ref:`database types <database-types>`.
.. index:: boolean, float, int, string, date
.. _primitive-types:
@@ -479,6 +480,50 @@ program, so it's helpful to extend a new type (namely ``TTaintType``)::
class Tainted extends TaintType, TTaintedValue {
}
.. _type-unions:
Type unions
***********
Type unions are user-defined types that are declared with the keyword ``class``.
The syntax resembles :ref:`type aliases <type-aliases>`, but with two or more type expressions on the right-hand side.
Type unions are used for creating restricted subsets of an existing :ref:`algebraic datatype <algebraic-datatypes>`, by explicitly
selecting a subset of the branches of that datatype and binding them to a new type.
Type unions of :ref:`database types <database-types>` are also supported.
You can use a type union to give a name to a subset of the branches from an algebraic datatype.
In some cases, using the type union over the whole algebraic datatype can avoid spurious
:ref:`recursion <recursion>` in predicates.
For example, the following construction is legal::
newtype InitialValueSource =
ExplicitInitialization(VarDecl v) { exists(v.getInitializer()) } or
ParameterPassing(Call c, int pos) { exists(c.getParameter(pos)) } or
UnknownInitialGarbage(VarDecl v) { not exists(DefiniteInitialization di | v = target(di)) }
class DefiniteInitialization = ParameterPassing or ExplicitInitialization;
VarDecl target(DefiniteInitialization di) {
di = ExplicitInitialization(result) or
exists(Call c, int pos | di = ParameterPassing(c, pos) and
result = c.getCallee().getFormalArg(pos))
}
However, a similar implementation that restricts ``InitialValueSource`` in a class extension is not valid.
If we had implemented ``DefiniteInitialization`` as a class extension instead, it would trigger a type test for ``InitialValueSource``. This results in an illegal recursion ``DefiniteInitialization -> InitialValueSource -> UnknownInitialGarbage -> ¬DefiniteInitialization`` since ``UnknownInitialGarbage`` relies on ``DefiniteInitialization``::
// THIS WON'T WORK: The implicit type check for InitialValueSource involves an illegal recursion
// DefiniteInitialization -> InitialValueSource -> UnknownInitialGarbage -> ¬DefiniteInitialization!
class DefiniteInitialization extends InitialValueSource {
DefiniteInitialization() {
this instanceof ParameterPassing or this instanceof ExplicitInitialization
}
// ...
}
Type unions are supported from release 2.2.0 of the CodeQL CLI.
.. _database-types:
Database types

View File

@@ -0,0 +1,12 @@
public Object evaluate(Socket socket) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
String string = reader.readLine();
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression(string);
SimpleEvaluationContext context
= SimpleEvaluationContext.forReadWriteDataBinding().build();
return expression.getValue(context);
}
}

View File

@@ -0,0 +1,56 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
The Spring Expression Language (SpEL) is a powerful expression language
provided by Spring Framework. The language offers many features
including invocation of methods available in the JVM.
If a SpEL expression is built using attacker-controlled data,
and then evaluated in a powerful context,
then it may allow the attacker to run arbitrary code.
</p>
<p>
The <code>SpelExpressionParser</code> class parses a SpEL expression string
and returns an <code>Expression</code> instance
that can be then evaluated by calling one of its methods.
By default, an expression is evaluated in a powerful <code>StandardEvaluationContext</code>
that allows the expression to access other methods available in the JVM.
</p>
</overview>
<recommendation>
<p>
In general, including user input in a SpEL expression should be avoided.
If user input must be included in the expression,
it should be then evaluated in a limited context
that doesn't allow arbitrary method invocation.
</p>
</recommendation>
<example>
<p>
The following example uses untrusted data to build a SpEL expression
and then runs it in the default powerfull context.
</p>
<sample src="UnsafeSpelExpressionEvaluation.java" />
<p>
The next example shows how an untrusted SpEL expression can be run
in <code>SimpleEvaluationContext</code> that doesn't allow accessing arbitrary methods.
However, it's recommended to avoid using untrusted input in SpEL expressions.
</p>
<sample src="SaferSpelExpressionEvaluation.java" />
</example>
<references>
<li>
Spring Framework Reference Documentation:
<a href="https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/expressions.html">Spring Expression Language (SpEL)</a>.
</li>
<li>
OWASP:
<a href="https://owasp.org/www-community/vulnerabilities/Expression_Language_Injection">Expression Language Injection</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,19 @@
/**
* @name Expression language injection (Spring)
* @description Evaluation of a user-controlled Spring Expression Language (SpEL) expression
* may lead to remote code execution.
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/spel-expression-injection
* @tags security
* external/cwe/cwe-094
*/
import java
import SpelInjectionLib
import DataFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink, ExpressionInjectionConfig conf
where conf.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "SpEL injection from $@.", source.getNode(), "this user input"

View File

@@ -0,0 +1,100 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking2
import SpringFrameworkLib
/**
* A taint-tracking configuration for unsafe user input
* that is used to construct and evaluate a SpEL expression.
*/
class ExpressionInjectionConfig extends TaintTracking::Configuration {
ExpressionInjectionConfig() { this = "ExpressionInjectionConfig" }
override predicate isSource(DataFlow::Node source) {
source instanceof RemoteFlowSource or
source instanceof WebRequestSource
}
override predicate isSink(DataFlow::Node sink) { sink instanceof ExpressionEvaluationSink }
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
expressionParsingStep(node1, node2) or
springPropertiesStep(node1, node2)
}
}
/**
* A sink for SpEL injection vulnerabilities,
* i.e. methods that run evaluation of a SpEL expression in a powerfull context.
*/
class ExpressionEvaluationSink extends DataFlow::ExprNode {
ExpressionEvaluationSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
m instanceof ExpressionEvaluationMethod and
getExpr() = ma.getQualifier() and
not exists(SafeEvaluationContextFlowConfig config |
config.hasFlowTo(DataFlow::exprNode(ma.getArgument(0)))
)
)
}
}
/**
* Holds if `node1` to `node2` is a dataflow step that parses a SpEL expression,
* i.e. `parser.parseExpression(tainted)`.
*/
predicate expressionParsingStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma, Method m | ma.getMethod() = m |
m.getDeclaringType().getAnAncestor*() instanceof ExpressionParser and
m.hasName("parseExpression") and
ma.getAnArgument() = node1.asExpr() and
node2.asExpr() = ma
)
}
/**
* A configuration for safe evaluation context that may be used in expression evaluation.
*/
class SafeEvaluationContextFlowConfig extends DataFlow2::Configuration {
SafeEvaluationContextFlowConfig() { this = "SpelInjection::SafeEvaluationContextFlowConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof SafeContextSource }
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
m instanceof ExpressionEvaluationMethod and
ma.getArgument(0) = sink.asExpr()
)
}
override int fieldFlowBranchLimit() { result = 0 }
}
class SafeContextSource extends DataFlow::ExprNode {
SafeContextSource() {
isSimpleEvaluationContextConstructorCall(getExpr()) or
isSimpleEvaluationContextBuilderCall(getExpr())
}
}
/**
* Holds if `expr` constructs `SimpleEvaluationContext`.
*/
predicate isSimpleEvaluationContextConstructorCall(Expr expr) {
exists(ConstructorCall cc |
cc.getConstructedType() instanceof SimpleEvaluationContext and
cc = expr
)
}
/**
* Holds if `expr` builds `SimpleEvaluationContext` via `SimpleEvaluationContext.Builder`,
* e.g. `SimpleEvaluationContext.forReadWriteDataBinding().build()`.
*/
predicate isSimpleEvaluationContextBuilderCall(Expr expr) {
exists(MethodAccess ma, Method m | ma.getMethod() = m |
m.getDeclaringType() instanceof SimpleEvaluationContextBuilder and
m.hasName("build") and
ma = expr
)
}

View File

@@ -0,0 +1,136 @@
import java
import semmle.code.java.dataflow.DataFlow
/**
* Methods that trigger evaluation of an expression.
*/
class ExpressionEvaluationMethod extends Method {
ExpressionEvaluationMethod() {
getDeclaringType() instanceof Expression and
(
hasName("getValue") or
hasName("getValueTypeDescriptor") or
hasName("getValueType") or
hasName("setValue")
)
}
}
/**
* `WebRequest` interface is a source of tainted data.
*/
class WebRequestSource extends DataFlow::Node {
WebRequestSource() {
exists(MethodAccess ma, Method m | ma.getMethod() = m |
m.getDeclaringType() instanceof WebRequest and
(
m.hasName("getHeader") or
m.hasName("getHeaderValues") or
m.hasName("getHeaderNames") or
m.hasName("getParameter") or
m.hasName("getParameterValues") or
m.hasName("getParameterNames") or
m.hasName("getParameterMap")
) and
ma = asExpr()
)
}
}
/**
* Holds if `node1` to `node2` is a dataflow step that converts `PropertyValues`
* to an array of `PropertyValue`, i.e. `tainted.getPropertyValues()`.
*/
predicate getPropertyValuesStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
node1.asExpr() = ma.getQualifier() and
node2.asExpr() = ma and
m.getDeclaringType() instanceof PropertyValues and
m.hasName("getPropertyValues")
)
}
/**
* Holds if `node1` to `node2` is a dataflow step that constructs `MutablePropertyValues`,
* i.e. `new MutablePropertyValues(tainted)`.
*/
predicate createMutablePropertyValuesStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(ConstructorCall cc | cc.getConstructedType() instanceof MutablePropertyValues |
node1.asExpr() = cc.getAnArgument() and
node2.asExpr() = cc
)
}
/**
* Holds if `node1` to `node2` is a dataflow step that returns a name of `PropertyValue`,
* i.e. `tainted.getName()`.
*/
predicate getPropertyNameStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
node1.asExpr() = ma.getQualifier() and
node2.asExpr() = ma and
m.getDeclaringType() instanceof PropertyValue and
m.hasName("getName")
)
}
/**
* Holds if `node1` to `node2` is a dataflow step that converts `MutablePropertyValues`
* to a list of `PropertyValue`, i.e. `tainted.getPropertyValueList()`.
*/
predicate getPropertyValueListStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(MethodAccess ma, Method m | m = ma.getMethod() |
node1.asExpr() = ma.getQualifier() and
node2.asExpr() = ma and
m.getDeclaringType() instanceof MutablePropertyValues and
m.hasName("getPropertyValueList")
)
}
/**
* Holds if `node1` to `node2` is one of the dataflow steps that propagate
* tainted data via Spring properties.
*/
predicate springPropertiesStep(DataFlow::Node node1, DataFlow::Node node2) {
createMutablePropertyValuesStep(node1, node2) or
getPropertyNameStep(node1, node2) or
getPropertyValuesStep(node1, node2) or
getPropertyValueListStep(node1, node2)
}
class PropertyValue extends RefType {
PropertyValue() { hasQualifiedName("org.springframework.beans", "PropertyValue") }
}
class PropertyValues extends RefType {
PropertyValues() { hasQualifiedName("org.springframework.beans", "PropertyValues") }
}
class MutablePropertyValues extends RefType {
MutablePropertyValues() { hasQualifiedName("org.springframework.beans", "MutablePropertyValues") }
}
class SimpleEvaluationContext extends RefType {
SimpleEvaluationContext() {
hasQualifiedName("org.springframework.expression.spel.support", "SimpleEvaluationContext")
}
}
class SimpleEvaluationContextBuilder extends RefType {
SimpleEvaluationContextBuilder() {
hasQualifiedName("org.springframework.expression.spel.support",
"SimpleEvaluationContext$Builder")
}
}
class WebRequest extends RefType {
WebRequest() { hasQualifiedName("org.springframework.web.context.request", "WebRequest") }
}
class Expression extends RefType {
Expression() { hasQualifiedName("org.springframework.expression", "Expression") }
}
class ExpressionParser extends RefType {
ExpressionParser() { hasQualifiedName("org.springframework.expression", "ExpressionParser") }
}

View File

@@ -0,0 +1,10 @@
public Object evaluate(Socket socket) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
String string = reader.readLine();
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression(string);
return expression.getValue();
}
}

View File

@@ -305,6 +305,21 @@ private predicate instanceOfGuarded(VarAccess va, RefType t) {
)
}
/**
* Holds if `aa` is an access to a value that is guarded by `instanceof t`.
*/
predicate arrayInstanceOfGuarded(ArrayAccess aa, RefType t) {
exists(InstanceOfExpr ioe, BaseSsaVariable v1, BaseSsaVariable v2, ArrayAccess aa1 |
ioe.getExpr() = aa1 and
t = ioe.getTypeName().getType() and
aa1.getArray() = v1.getAUse() and
aa1.getIndexExpr() = v2.getAUse() and
aa.getArray() = v1.getAUse() and
aa.getIndexExpr() = v2.getAUse() and
guardControls_v1(ioe, aa.getBasicBlock(), true)
)
}
/**
* Holds if `n` has type `t` and this information is discarded, such that `t`
* might be a better type bound for nodes where `n` flows to.
@@ -315,6 +330,7 @@ private predicate typeFlowBase(TypeFlowNode n, RefType t) {
upcastEnhancedForStmt(n.asSsa(), srctype) or
downcastSuccessor(n.asExpr(), srctype) or
instanceOfGuarded(n.asExpr(), srctype) or
arrayInstanceOfGuarded(n.asExpr(), srctype) or
n.asExpr().(FunctionalExpr).getConstructedType() = srctype
|
t = srctype.(BoundedType).getAnUltimateUpperBoundType()

View File

@@ -0,0 +1,27 @@
edges
| SpelInjection.java:15:22:15:44 | getInputStream(...) : InputStream | SpelInjection.java:23:5:23:14 | expression |
| SpelInjection.java:27:22:27:44 | getInputStream(...) : InputStream | SpelInjection.java:34:5:34:14 | expression |
| SpelInjection.java:38:22:38:44 | getInputStream(...) : InputStream | SpelInjection.java:48:5:48:14 | expression |
| SpelInjection.java:52:22:52:44 | getInputStream(...) : InputStream | SpelInjection.java:59:5:59:14 | expression |
| SpelInjection.java:63:22:63:44 | getInputStream(...) : InputStream | SpelInjection.java:70:5:70:14 | expression |
| SpelInjection.java:74:22:74:44 | getInputStream(...) : InputStream | SpelInjection.java:83:5:83:14 | expression |
nodes
| SpelInjection.java:15:22:15:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SpelInjection.java:23:5:23:14 | expression | semmle.label | expression |
| SpelInjection.java:27:22:27:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SpelInjection.java:34:5:34:14 | expression | semmle.label | expression |
| SpelInjection.java:38:22:38:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SpelInjection.java:48:5:48:14 | expression | semmle.label | expression |
| SpelInjection.java:52:22:52:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SpelInjection.java:59:5:59:14 | expression | semmle.label | expression |
| SpelInjection.java:63:22:63:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SpelInjection.java:70:5:70:14 | expression | semmle.label | expression |
| SpelInjection.java:74:22:74:44 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| SpelInjection.java:83:5:83:14 | expression | semmle.label | expression |
#select
| SpelInjection.java:23:5:23:14 | expression | SpelInjection.java:15:22:15:44 | getInputStream(...) : InputStream | SpelInjection.java:23:5:23:14 | expression | SpEL injection from $@. | SpelInjection.java:15:22:15:44 | getInputStream(...) | this user input |
| SpelInjection.java:34:5:34:14 | expression | SpelInjection.java:27:22:27:44 | getInputStream(...) : InputStream | SpelInjection.java:34:5:34:14 | expression | SpEL injection from $@. | SpelInjection.java:27:22:27:44 | getInputStream(...) | this user input |
| SpelInjection.java:48:5:48:14 | expression | SpelInjection.java:38:22:38:44 | getInputStream(...) : InputStream | SpelInjection.java:48:5:48:14 | expression | SpEL injection from $@. | SpelInjection.java:38:22:38:44 | getInputStream(...) | this user input |
| SpelInjection.java:59:5:59:14 | expression | SpelInjection.java:52:22:52:44 | getInputStream(...) : InputStream | SpelInjection.java:59:5:59:14 | expression | SpEL injection from $@. | SpelInjection.java:52:22:52:44 | getInputStream(...) | this user input |
| SpelInjection.java:70:5:70:14 | expression | SpelInjection.java:63:22:63:44 | getInputStream(...) : InputStream | SpelInjection.java:70:5:70:14 | expression | SpEL injection from $@. | SpelInjection.java:63:22:63:44 | getInputStream(...) | this user input |
| SpelInjection.java:83:5:83:14 | expression | SpelInjection.java:74:22:74:44 | getInputStream(...) : InputStream | SpelInjection.java:83:5:83:14 | expression | SpEL injection from $@. | SpelInjection.java:74:22:74:44 | getInputStream(...) | this user input |

View File

@@ -0,0 +1,100 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class SpelInjection {
private static final ExpressionParser PARSER = new SpelExpressionParser();
public void testGetValue(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int n = in.read(bytes);
String input = new String(bytes, 0, n);
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression(input);
expression.getValue();
}
public void testGetValueWithChainedCalls(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int n = in.read(bytes);
String input = new String(bytes, 0, n);
Expression expression = new SpelExpressionParser().parseExpression(input);
expression.getValue();
}
public void testSetValueWithRootObject(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int n = in.read(bytes);
String input = new String(bytes, 0, n);
Expression expression = new SpelExpressionParser().parseExpression(input);
Object root = new Object();
Object value = new Object();
expression.setValue(root, value);
}
public void testGetValueWithStaticParser(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int n = in.read(bytes);
String input = new String(bytes, 0, n);
Expression expression = PARSER.parseExpression(input);
expression.getValue();
}
public void testGetValueType(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int n = in.read(bytes);
String input = new String(bytes, 0, n);
Expression expression = PARSER.parseExpression(input);
expression.getValueType();
}
public void testWithStandardEvaluationContext(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int n = in.read(bytes);
String input = new String(bytes, 0, n);
Expression expression = PARSER.parseExpression(input);
StandardEvaluationContext context = new StandardEvaluationContext();
expression.getValue(context);
}
public void testWithSimpleEvaluationContext(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int n = in.read(bytes);
String input = new String(bytes, 0, n);
Expression expression = PARSER.parseExpression(input);
SimpleEvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
// the expression is evaluated in a limited context
expression.getValue(context);
}
}

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-094/SpelInjection.ql

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3

View File

@@ -85,4 +85,11 @@ public class A extends ArrayList<Long> {
empty.put(k, v);
}
}
public void m8(Object[] xs, int i) {
if (xs[i] instanceof Integer) {
Object n = xs[i];
Object r = n;
}
}
}

View File

@@ -12,3 +12,4 @@
| A.java:61:11:61:11 | x | Integer | false |
| A.java:67:22:67:22 | x | Integer | false |
| A.java:70:23:70:24 | x2 | Integer | false |
| A.java:92:18:92:18 | n | Integer | false |

View File

@@ -0,0 +1,3 @@
package org.springframework.expression;
public interface EvaluationContext {}

View File

@@ -0,0 +1,3 @@
package org.springframework.expression;
public class EvaluationException extends RuntimeException {}

View File

@@ -0,0 +1,14 @@
package org.springframework.expression;
public interface Expression {
Object getValue() throws EvaluationException;
Object getValue(EvaluationContext context) throws EvaluationException;
Class<?> getValueType() throws EvaluationException;
Class<?> getValueType(EvaluationContext context) throws EvaluationException;
void setValue(Object rootObject, Object value) throws EvaluationException;
}

View File

@@ -0,0 +1,6 @@
package org.springframework.expression;
public interface ExpressionParser {
Expression parseExpression(String string);
}

View File

@@ -0,0 +1,10 @@
package org.springframework.expression.spel.standard;
import org.springframework.expression.*;
public class SpelExpressionParser implements ExpressionParser {
public SpelExpressionParser() {}
public Expression parseExpression(String string) { return null; }
}

View File

@@ -0,0 +1,13 @@
package org.springframework.expression.spel.support;
import org.springframework.expression.*;
public class SimpleEvaluationContext implements EvaluationContext {
public static Builder forReadWriteDataBinding() { return null; }
public static class Builder {
public SimpleEvaluationContext build() { return null; }
}
}

View File

@@ -0,0 +1,5 @@
package org.springframework.expression.spel.support;
import org.springframework.expression.*;
public class StandardEvaluationContext implements EvaluationContext {}

View File

@@ -61,18 +61,14 @@ DataFlow::Node schemeCheck(DataFlow::Node nd, DangerousScheme scheme) {
sw.getSubstring().mayHaveStringValue(scheme)
)
or
// check of the form `array.includes(getScheme(nd))`
exists(InclusionTest test, DataFlow::ArrayCreationNode array | test = result |
schemeOf(nd).flowsTo(test.getContainedNode()) and
array.flowsTo(test.getContainerNode()) and
array.getAnElement().mayHaveStringValue(scheme.getWithOrWithoutColon())
)
or
// check of the form `getScheme(nd) === scheme`
exists(EqualityTest test, Expr op1, Expr op2 | test.flow() = result |
test.hasOperands(op1, op2) and
schemeOf(nd).flowsToExpr(op1) and
op2.mayHaveStringValue(scheme.getWithOrWithoutColon())
exists(MembershipCandidate candidate |
result = candidate.getTest()
or
// fall back to the candidate if the test itself is implicit
not exists(candidate.getTest()) and result = candidate
|
candidate.getAMemberString() = scheme.getWithOrWithoutColon() and
schemeOf(nd).flowsTo(candidate)
)
or
// propagate through trimming, case conversion, and regexp replace

View File

@@ -449,8 +449,10 @@ class BlacklistInclusionGuard extends DataFlow::LabeledBarrierGuardNode, Inclusi
*/
class WhitelistInclusionGuard extends DataFlow::LabeledBarrierGuardNode {
WhitelistInclusionGuard() {
this instanceof TaintTracking::PositiveIndexOfSanitizer or
this instanceof TaintTracking::InclusionSanitizer
this instanceof TaintTracking::PositiveIndexOfSanitizer
or
this instanceof TaintTracking::MembershipTestSanitizer and
not this = any(MembershipCandidate::ObjectPropertyNameMembershipCandidate c).getTest() // handled with more precision in `HasOwnPropertyGuard`
}
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {

View File

@@ -37,6 +37,7 @@ import semmle.javascript.JsonParsers
import semmle.javascript.JSX
import semmle.javascript.Lines
import semmle.javascript.Locations
import semmle.javascript.MembershipCandidates
import semmle.javascript.Modules
import semmle.javascript.NodeJS
import semmle.javascript.NPM

View File

@@ -108,6 +108,7 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode {
int getIntValue() { none() }
/** Gets the constant string value this expression evaluates to, if any. */
cached
string getStringValue() { none() }
/** Holds if this expression is impure, that is, its evaluation could have side effects. */
@@ -1354,6 +1355,11 @@ class EqualityTest extends @equalitytest, Comparison {
(this instanceof NEqExpr or this instanceof StrictNEqExpr) and
result = false
}
/**
* Holds if the equality operator is strict (`===` or `!==`).
*/
predicate isStrict() { this instanceof StrictEqExpr or this instanceof StrictNEqExpr }
}
/**

View File

@@ -5,7 +5,7 @@
private import javascript
/**
* A expression that checks if an element is contained in an array
* An expression that checks if an element is contained in an array
* or is a substring of another string.
*
* Examples:

View File

@@ -0,0 +1,261 @@
/**
* Provides classes for recognizing membership tests.
*/
import javascript
/**
* An expression that is tested for membership of a collection.
*
* Additional candidates can be added by subclassing `MembershipCandidate::Range`
*/
class MembershipCandidate extends DataFlow::Node {
MembershipCandidate::Range range;
MembershipCandidate() { this = range }
/**
* Gets the expression that performs the membership test, if any.
*/
DataFlow::Node getTest() { result = range.getTest() }
/**
* Gets a string that this candidate is tested against, if
* it can be determined.
*/
string getAMemberString() { result = range.getAMemberString() }
/**
* Gets a node that this candidate is tested against, if
* it can be determined.
*/
DataFlow::Node getAMemberNode() { result = range.getAMemberNode() }
/**
* Gets the polarity of the test.
*
* If the polarity is `false` the test returns `true` if the
* collection does not contain this candidate.
*/
boolean getTestPolarity() { result = range.getTestPolarity() }
}
/**
* Provides classes for recognizing membership candidates.
*/
module MembershipCandidate {
/**
* An expression that is tested for membership of a collection.
*/
abstract class Range extends DataFlow::Node {
/**
* Gets the expression that performs the membership test, if any.
*/
abstract DataFlow::Node getTest();
/**
* Gets a string that this candidate is tested against, if
* it can be determined.
*/
string getAMemberString() { this.getAMemberNode().mayHaveStringValue(result) }
/**
* Gets a node that this candidate is tested against, if
* it can be determined.
*/
DataFlow::Node getAMemberNode() { none() }
/**
* Gets the polarity of the test.
*
* If the polarity is `false` the test returns `true` if the
* collection does not contain this candidate.
*/
boolean getTestPolarity() { result = true }
}
/**
* An `InclusionTest` candidate viewed as a `MembershipCandidate`.
*/
private class OrdinaryInclusionTestCandidate extends MembershipCandidate::Range {
InclusionTest test;
OrdinaryInclusionTestCandidate() { this = test.getContainedNode() }
override DataFlow::Node getTest() { result = test }
override boolean getTestPolarity() { result = test.getPolarity() }
}
/**
* A candidate that may be a member of an array.
*/
class ArrayMembershipCandidate extends OrdinaryInclusionTestCandidate {
DataFlow::ArrayCreationNode array;
ArrayMembershipCandidate() { array.flowsTo(test.getContainerNode()) }
/**
* Gets the array of this test.
*/
DataFlow::ArrayCreationNode getArray() { result = array }
override DataFlow::Node getAMemberNode() { result = array.getAnElement() }
}
/**
* A candidate that may be a member of an array constructed
* from a call to `String.prototype.split`.
*/
private class ShorthandArrayMembershipCandidate extends OrdinaryInclusionTestCandidate {
string toSplit;
string separator;
ShorthandArrayMembershipCandidate() {
exists(StringSplitCall split |
split.flowsTo(test.getContainerNode()) and
toSplit = split.getBaseString().getStringValue() and
separator = split.getSeparator()
)
}
override string getAMemberString() { result = toSplit.splitAt(separator) }
}
/**
* An `EqualityTest` operand viewed as a `MembershipCandidate`.
*/
private class EqualityTestOperand extends MembershipCandidate::Range, DataFlow::ValueNode {
EqualityTest test;
EqualityTestOperand() { this = test.getAnOperand().flow() }
override DataFlow::Node getTest() { result = test.flow() }
override DataFlow::Node getAMemberNode() { test.hasOperands(this.asExpr(), result.asExpr()) }
override boolean getTestPolarity() { result = test.getPolarity() }
}
/**
* A regular expression that enumerates all of its matched strings.
*/
private class EnumerationRegExp extends RegExpTerm {
EnumerationRegExp() {
this.isRootTerm() and
RegExp::isFullyAnchoredTerm(this) and
exists(RegExpTerm child | this.getAChild*() = child |
child instanceof RegExpSequence or
child instanceof RegExpCaret or
child instanceof RegExpDollar or
child instanceof RegExpConstant or
child instanceof RegExpAlt or
child instanceof RegExpGroup
)
}
/**
* Gets a string matched by this regular expression.
*/
string getAMember() { result = this.getAChild*().getAMatchedString() }
}
/**
* A candidate that may be matched by a regular expression that
* enumerates all of its matched strings.
*/
private class RegExpEnumerationCandidate extends MembershipCandidate::Range, DataFlow::Node {
DataFlow::Node test;
EnumerationRegExp enumeration;
boolean polarity;
RegExpEnumerationCandidate() {
exists(DataFlow::MethodCallNode mcn, DataFlow::Node base, string m, DataFlow::Node firstArg |
(
test = any(ConditionGuardNode g).getTest().flow() and
mcn.flowsTo(test) and
polarity = true
or
exists(EqualityTest eq, Expr null, Expr op |
test = eq.flow() and
polarity = eq.getPolarity().booleanNot() and
mcn.flowsToExpr(op) and
eq.hasOperands(op, null) and
SyntacticConstants::isNull(null)
)
) and
mcn.calls(base, m) and
firstArg = mcn.getArgument(0)
|
// /re/.test(u) or /re/.exec(u)
enumeration = RegExp::getRegExpObjectFromNode(base) and
(m = "test" or m = "exec") and
firstArg = this
or
// u.match(/re/) or u.match("re")
base = this and
m = "match" and
enumeration = RegExp::getRegExpFromNode(firstArg)
)
}
override DataFlow::Node getTest() { result = test }
override string getAMemberString() { result = enumeration.getAMember() }
override boolean getTestPolarity() { result = polarity }
}
/**
* A candidate that may be a member of a collection class, such as a map or set.
*/
class CollectionMembershipCandidate extends MembershipCandidate::Range {
DataFlow::MethodCallNode test;
CollectionMembershipCandidate() { test.getMethodName() = "has" and this = test.getArgument(0) }
override DataFlow::Node getTest() { result = test }
}
/**
* A candidate that may be a property name of an object.
*/
class ObjectPropertyNameMembershipCandidate extends MembershipCandidate::Range,
DataFlow::ValueNode {
DataFlow::ValueNode test;
DataFlow::ValueNode membersNode;
ObjectPropertyNameMembershipCandidate() {
exists(InExpr inExpr |
this = inExpr.getLeftOperand().flow() and
test = inExpr.flow() and
membersNode = inExpr.getRightOperand().flow()
)
or
exists(DataFlow::MethodCallNode hasOwn |
this = hasOwn.getArgument(0) and
test = hasOwn and
hasOwn.calls(membersNode, "hasOwnProperty")
)
}
override DataFlow::Node getTest() { result = test }
override string getAMemberString() {
exists(membersNode.getALocalSource().getAPropertyWrite(result))
}
}
/**
* A candidate that may match a switch case.
*/
class SwitchCaseCandidate extends MembershipCandidate::Range {
SwitchStmt switch;
SwitchCaseCandidate() { this = switch.getExpr().flow() }
override DataFlow::Node getTest() { none() }
override DataFlow::Node getAMemberNode() { result = switch.getACase().getExpr().flow() }
}
}

View File

@@ -629,4 +629,153 @@ module StringOps {
class HtmlConcatenationLeaf extends ConcatenationLeaf {
HtmlConcatenationLeaf() { getRoot() instanceof HtmlConcatenationRoot }
}
/**
* A data flow node whose boolean value indicates whether a regexp matches a given string.
*
* For example, the condition of each of the following `if`-statements are `RegExpTest` nodes:
* ```js
* if (regexp.test(str)) { ... }
* if (regexp.exec(str) != null) { ... }
* if (str.matches(regexp)) { ... }
* ```
*
* Note that `RegExpTest` represents a boolean-valued expression or one
* that is coerced to a boolean, which is not always the same as the call that performs the
* regexp-matching. For example, the `exec` call below is not itself a `RegExpTest`,
* but the `match` variable in the condition is:
* ```js
* let match = regexp.exec(str);
* if (!match) { ... } // <--- 'match' is the RegExpTest
* ```
*/
class RegExpTest extends DataFlow::Node {
RegExpTest::Range range;
RegExpTest() { this = range }
/**
* Gets the AST of the regular expression used in the test, if it can be seen locally.
*/
RegExpTerm getRegExp() {
result = getRegExpOperand().getALocalSource().(DataFlow::RegExpCreationNode).getRoot()
or
result = range.getRegExpOperand(true).asExpr().(StringLiteral).asRegExp()
}
/**
* Gets the data flow node corresponding to the regular expression object used in the test.
*
* In some cases this represents a string value being coerced to a RegExp object.
*/
DataFlow::Node getRegExpOperand() { result = range.getRegExpOperand(_) }
/**
* Gets the data flow node corresponding to the string being tested against the regular expression.
*/
DataFlow::Node getStringOperand() { result = range.getStringOperand() }
/**
* Gets the return value indicating that the string matched the regular expression.
*
* For example, for `regexp.exec(str) == null`, the polarity is `false`, and for
* `regexp.exec(str) != null` the polarity is `true`.
*/
boolean getPolarity() { result = range.getPolarity() }
}
/**
* Companion module to the `RegExpTest` class.
*/
module RegExpTest {
/**
* A data flow node whose boolean value indicates whether a regexp matches a given string.
*
* This class can be extended to contribute new kinds of `RegExpTest` nodes.
*/
abstract class Range extends DataFlow::Node {
/**
* Gets the data flow node corresponding to the regular expression object used in the test.
*/
abstract DataFlow::Node getRegExpOperand(boolean coerced);
/**
* Gets the data flow node corresponding to the string being tested against the regular expression.
*/
abstract DataFlow::Node getStringOperand();
/**
* Gets the return value indicating that the string matched the regular expression.
*/
boolean getPolarity() { result = true }
}
private class TestCall extends Range, DataFlow::MethodCallNode {
TestCall() { getMethodName() = "test" }
override DataFlow::Node getRegExpOperand(boolean coerced) {
result = getReceiver() and coerced = false
}
override DataFlow::Node getStringOperand() { result = getArgument(0) }
}
private class MatchesCall extends Range, DataFlow::MethodCallNode {
MatchesCall() { getMethodName() = "matches" }
override DataFlow::Node getRegExpOperand(boolean coerced) {
result = getArgument(0) and coerced = true
}
override DataFlow::Node getStringOperand() { result = getReceiver() }
}
private class ExecCall extends DataFlow::MethodCallNode {
ExecCall() { getMethodName() = "exec" }
}
private predicate isCoercedToBoolean(Expr e) {
e = any(ConditionGuardNode guard).getTest()
or
e = any(LogNotExpr n).getOperand()
}
/**
* Holds if `e` evaluating to `polarity` implies that `operand` is not null.
*/
private predicate impliesNotNull(Expr e, Expr operand, boolean polarity) {
exists(EqualityTest test, Expr other |
e = test and
polarity = test.getPolarity().booleanNot() and
test.hasOperands(other, operand) and
SyntacticConstants::isNullOrUndefined(other) and
not (
// 'exec() === undefined' doesn't work
other instanceof SyntacticConstants::UndefinedConstant and
test.isStrict()
)
)
or
isCoercedToBoolean(e) and
operand = e and
polarity = true
}
private class ExecTest extends Range, DataFlow::ValueNode {
ExecCall exec;
boolean polarity;
ExecTest() {
exists(Expr use | exec.flowsToExpr(use) | impliesNotNull(astNode, use, polarity))
}
override DataFlow::Node getRegExpOperand(boolean coerced) {
result = exec.getReceiver() and coerced = false
}
override DataFlow::Node getStringOperand() { result = exec.getArgument(0) }
override boolean getPolarity() { result = polarity }
}
}
}

View File

@@ -438,7 +438,10 @@ private predicate barrierGuardBlocksNode(BarrierGuardNode guard, DataFlow::Node
barrierGuardIsRelevant(guard) and
exists(AccessPath p, BasicBlock bb, ConditionGuardNode cond, boolean outcome |
nd = DataFlow::valueNode(p.getAnInstanceIn(bb)) and
guard.getEnclosingExpr() = cond.getTest() and
(
guard.getEnclosingExpr() = cond.getTest() or
guard = cond.getTest().flow().getImmediatePredecessor+()
) and
outcome = cond.getOutcome() and
barrierGuardBlocksAccessPath(guard, outcome, p, label) and
cond.dominates(bb)

View File

@@ -827,6 +827,29 @@ module TaintTracking {
override predicate appliesTo(Configuration cfg) { any() }
}
/** A check of the form `type x === "undefined"`, which sanitized `x` in its "then" branch. */
class TypeOfUndefinedSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
Expr x;
override EqualityTest astNode;
TypeOfUndefinedSanitizer() {
exists(StringLiteral str, TypeofExpr typeof | astNode.hasOperands(str, typeof) |
str.getValue() = "undefined" and
typeof.getOperand() = x
)
}
override predicate sanitizes(boolean outcome, Expr e) {
outcome = astNode.getPolarity() and
e = x
}
override predicate appliesTo(Configuration cfg) { any() }
}
/** DEPRECATED. This class has been renamed to `MembershipTestSanitizer`. */
deprecated class StringInclusionSanitizer = MembershipTestSanitizer;
/**
* A test of form `x.length === "0"`, preventing `x` from being tainted.
*/
@@ -849,18 +872,19 @@ module TaintTracking {
override predicate appliesTo(Configuration cfg) { any() }
}
/** DEPRECATED. This class has been renamed to `InclusionSanitizer`. */
deprecated class StringInclusionSanitizer = InclusionSanitizer;
/** DEPRECATED. This class has been renamed to `MembershipTestSanitizer`. */
deprecated class InclusionSanitizer = MembershipTestSanitizer;
/** A check of the form `whitelist.includes(x)` or equivalent, which sanitizes `x` in its "then" branch. */
class InclusionSanitizer extends AdditionalSanitizerGuardNode {
InclusionTest inclusion;
/**
* A check of the form `whitelist.includes(x)` or equivalent, which sanitizes `x` in its "then" branch.
*/
class MembershipTestSanitizer extends AdditionalSanitizerGuardNode {
MembershipCandidate candidate;
InclusionSanitizer() { this = inclusion }
MembershipTestSanitizer() { this = candidate.getTest() }
override predicate sanitizes(boolean outcome, Expr e) {
outcome = inclusion.getPolarity() and
e = inclusion.getContainedNode().asExpr()
candidate = e.flow() and candidate.getTestPolarity() = outcome
}
override predicate appliesTo(Configuration cfg) { any() }
@@ -895,8 +919,12 @@ module TaintTracking {
/** Gets a variable that is defined exactly once. */
private Variable singleDef() { strictcount(result.getADefinition()) = 1 }
/** A check of the form `if(x == 'some-constant')`, which sanitizes `x` in its "then" branch. */
class ConstantComparison extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
/**
* A check of the form `if(x == 'some-constant')`, which sanitizes `x` in its "then" branch.
*
* DEPRECATED: use `MembershipTestSanitizer` instead.
*/
deprecated class ConstantComparison extends SanitizerGuardNode, DataFlow::ValueNode {
Expr x;
override EqualityTest astNode;
@@ -914,7 +942,10 @@ module TaintTracking {
outcome = astNode.getPolarity() and x = e
}
override predicate appliesTo(Configuration cfg) { any() }
/**
* Holds if this guard applies to the flow in `cfg`.
*/
predicate appliesTo(Configuration cfg) { any() }
}
/**

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