Merge remote-tracking branch 'upstream/master' into dataflow-TTwo

Conflicts:
      cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll
      cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll
      cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll
      cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll
      cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll
      cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll
      cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll
      cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll
      cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll
      cpp/ql/test/library-tests/dataflow/fields/flow.expected
      csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
      csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll
      csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll
      csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll
      csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll
      java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll
      java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll
      java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll
      java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll
      java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll
This commit is contained in:
Jonas Jensen
2019-09-08 21:08:43 +02:00
428 changed files with 8105 additions and 2374 deletions

View File

@@ -8,13 +8,16 @@ The following changes in version 1.23 affect C/C++ analysis in all applications.
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
| Query name (`query id`) | tags | Message. |
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). |
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------|
| Query name (`query id`) | Expected impact | Message. |
| Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) | Deprecated | This query has been deprecated. Use the new combined query Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) instead. |
| Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`) | Deprecated | This query has been deprecated. Use the new combined query Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) instead. |
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | More correct results | This query now checks for the beginning date of the Reiwa era (1st May 2019). |
## Changes to QL libraries
@@ -25,3 +28,10 @@ The following changes in version 1.23 affect C/C++ analysis in all applications.
picture of the partial flow paths from a given source. The feature is
disabled by default and can be enabled for individual configurations by
overriding `int explorationLimit()`.
* The `DataFlow::DefinitionByReferenceNode` class now considers `f(x)` to be a
definition of `x` when `x` is a variable of pointer type. It no longer
considers deep paths such as `f(&x.myField)` to be definitions of `x`. These
changes are in line with the user expectations we've observed.
* There is now a `DataFlow::localExprFlow` predicate and a
`TaintTracking::localExprTaint` predicate to make it easy to use the most
common case of local data flow and taint: from one `Expr` to another.

View File

@@ -18,6 +18,7 @@
| **Query** | **Expected impact** | **Change** |
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
| Client-side cross-site scripting (`js/xss`) | More results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized. |
| Prototype pollution (`js/prototype-pollution`) | More results | The query now highlights vulnerable uses of jQuery and Angular, and the results are shown on LGTM by default. |
## Changes to QL libraries

View File

@@ -0,0 +1,7 @@
[[ condition: enterprise-only ]]
# Improvements to JavaScript analysis
## Changes to code extraction
* Asynchronous generator methods are now parsed correctly and no longer cause a spurious syntax error.

View File

@@ -0,0 +1,17 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
When eras change, date and time conversions that rely on a hard-coded era start date need to be reviewed. Conversions relying on Japanese dates in the current era can produce an ambiguous date.
The values for the current Japanese era dates should be read from a source that will be updated, such as the Windows registry.
</p>
</overview>
<references>
<li>
<a href="https://blogs.msdn.microsoft.com/shawnste/2018/04/12/the-japanese-calendars-y2k-moment/">The Japanese Calendar's Y2K Moment</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,73 @@
/**
* @name Hard-coded Japanese era start date
* @description Japanese era changes can lead to code behaving differently. Avoid hard-coding Japanese era start dates.
* @kind problem
* @problem.severity warning
* @id cpp/japanese-era/exact-era-date
* @precision medium
* @tags reliability
* japanese-era
*/
import cpp
import semmle.code.cpp.commons.DateTime
predicate assignedYear(Struct s, YearFieldAccess year, int value) {
exists(Operation yearAssignment |
s.getAField().getAnAccess() = year and
yearAssignment.getAnOperand() = year and
yearAssignment.getAnOperand().getValue().toInt() = value
)
}
predicate assignedMonth(Struct s, MonthFieldAccess month, int value) {
exists(Operation monthAssignment |
s.getAField().getAnAccess() = month and
monthAssignment.getAnOperand() = month and
monthAssignment.getAnOperand().getValue().toInt() = value
)
}
predicate assignedDay(Struct s, DayFieldAccess day, int value) {
exists(Operation dayAssignment |
s.getAField().getAnAccess() = day and
dayAssignment.getAnOperand() = day and
dayAssignment.getAnOperand().getValue().toInt() = value
)
}
predicate eraDate(int year, int month, int day) {
year = 1989 and month = 1 and day = 8
or
year = 2019 and month = 5 and day = 1
}
predicate badStructInitialization(Element target, string message) {
exists(
StructLikeClass s, YearFieldAccess year, MonthFieldAccess month, DayFieldAccess day,
int yearValue, int monthValue, int dayValue
|
eraDate(yearValue, monthValue, dayValue) and
assignedYear(s, year, yearValue) and
assignedMonth(s, month, monthValue) and
assignedDay(s, day, dayValue) and
target = year and
message = "A time struct that is initialized with exact Japanese calendar era start date."
)
}
predicate badCall(Element target, string message) {
exists(Call cc, int i |
eraDate(cc.getArgument(i).getValue().toInt(), cc.getArgument(i + 1).getValue().toInt(),
cc.getArgument(i + 2).getValue().toInt()) and
target = cc and
message = "Call that appears to have hard-coded Japanese era start date as parameter."
)
}
from Element target, string message
where
badStructInitialization(target, message) or
badCall(target, message)
select target, message

View File

@@ -47,7 +47,7 @@ predicate allocExprOrIndirect(Expr alloc, string kind) {
or
exists(Expr e |
allocExprOrIndirect(e, kind) and
DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(rtn.getExpr()))
DataFlow::localExprFlow(e, rtn.getExpr())
)
)
)

View File

@@ -95,7 +95,7 @@ class CallWithBufferSize extends FunctionCall {
int statedSizeValue() {
exists(Expr statedSizeSrc |
DataFlow::localFlow(DataFlow::exprNode(statedSizeSrc), DataFlow::exprNode(statedSizeExpr())) and
DataFlow::localExprFlow(statedSizeSrc, statedSizeExpr()) and
result = statedSizeSrc.getValue().toInt()
)
}

View File

@@ -55,7 +55,7 @@ predicate whiteListWrapped(FunctionCall fc) {
whitelistPow(fc) or
exists(Expr e, ReturnStmt rs |
whiteListWrapped(e) and
DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(rs.getExpr())) and
DataFlow::localExprFlow(e, rs.getExpr()) and
fc.getTarget() = rs.getEnclosingFunction()
)
}

View File

@@ -1,5 +1,5 @@
/**
* @name Hard-coded Japanese era start date
* @name Hard-coded Japanese era start date in call
* @description Japanese era changes can lead to code behaving differently. Avoid hard-coding Japanese era start dates.
* @kind problem
* @problem.severity warning
@@ -7,6 +7,9 @@
* @precision medium
* @tags reliability
* japanese-era
* @deprecated This query is deprecated, use
* Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`)
* instead.
*/
import cpp

View File

@@ -1,5 +1,5 @@
/**
* @name Hard-coded Japanese era start date
* @name Hard-coded Japanese era start date in struct
* @description Japanese era changes can lead to code behaving differently. Avoid hard-coding Japanese era start dates.
* @kind problem
* @problem.severity warning
@@ -7,6 +7,9 @@
* @precision medium
* @tags reliability
* japanese-era
* @deprecated This query is deprecated, use
* Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`)
* instead.
*/
import cpp

View File

@@ -4,7 +4,6 @@
import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.commons.DateTime
/**

View File

@@ -23,7 +23,7 @@ predicate isBoolean(Expr e1) {
}
predicate isStringCopyCastedAsBoolean(FunctionCall func, Expr expr1, string msg) {
DataFlow::localFlow(DataFlow::exprNode(func), DataFlow::exprNode(expr1)) and
DataFlow::localExprFlow(func, expr1) and
isBoolean(expr1.getConversion*()) and
func.getTarget() instanceof StrcpyFunction and
msg = "Return value of " + func.getTarget().getName() + " used as a Boolean."

View File

@@ -10,8 +10,9 @@
* security
* external/cwe/cwe-676
* @deprecated This query is deprecated, use
* Security/CWE/CWE-120/OverrunWrite.ql and
* Security/CWE/CWE-120/OverrunWriteFloat.ql instead.
* Potentially overrunning write (`cpp/overrunning-write`) and
* Potentially overrunning write with float to string conversion
* (`cpp/overrunning-write-with-float) instead.
*/
import cpp
import semmle.code.cpp.commons.Buffer

View File

@@ -8,8 +8,8 @@
* @problem.severity warning
* @tags reliability
* @deprecated This query is deprecated, and replaced by
* jsf/4.10 Classes/AV Rule 78.ql, which has far fewer false
* positives on typical code.
* No virtual destructor (`cpp/jsf/av-rule-78`), which has far
* fewer false positives on typical code.
*/
import cpp

View File

@@ -36,12 +36,10 @@ class MallocCall extends FunctionCall
predicate terminationProblem(MallocCall malloc, string msg) {
malloc.getAllocatedSize() instanceof StrlenCall and
not exists(DataFlow::Node def, DataFlow::Node use, FunctionCall fc, MemcpyFunction memcpy, int ix |
DataFlow::localFlow(def, use) and
def.asExpr() = malloc and
not exists(FunctionCall fc, MemcpyFunction memcpy, int ix |
DataFlow::localExprFlow(malloc, fc.getArgument(ix)) and
fc.getTarget() = memcpy and
memcpy.hasArrayOutput(ix) and
use.asExpr() = fc.getArgument(ix)
memcpy.hasArrayOutput(ix)
) and
msg = "This allocation does not include space to null-terminate the string."
}

View File

@@ -12,7 +12,7 @@
* external/cwe/cwe-197
* external/cwe/cwe-835
*
*/
*/
import cpp
import semmle.code.cpp.controlflow.Dominance

View File

@@ -11,8 +11,10 @@
*
* To use global (interprocedural) data flow, extend the class
* `DataFlow::Configuration` as documented on that class. To use local
* (intraprocedural) data flow, invoke `DataFlow::localFlow` or
* `DataFlow::LocalFlowStep` with arguments of type `DataFlow::Node`.
* (intraprocedural) data flow between expressions, call
* `DataFlow::localExprFlow`. For more general cases of local data flow, call
* `DataFlow::localFlow` or `DataFlow::localFlowStep` with arguments of type
* `DataFlow::Node`.
*/
import cpp

View File

@@ -6,6 +6,13 @@
* the information from the source is preserved at the sink. For example, taint
* propagates from `x` to `x + 100`, but it does not propagate from `x` to `x >
* 100` since we consider a single bit of information to be too little.
*
* To use global (interprocedural) taint tracking, extend the class
* `TaintTracking::Configuration` as documented on that class. To use local
* (intraprocedural) taint tracking between expressions, call
* `TaintTracking::localExprTaint`. For more general cases of local taint
* tracking, call `TaintTracking::localTaint` or
* `TaintTracking::localTaintStep` with arguments of type `DataFlow::Node`.
*/
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.dataflow.DataFlow2

View File

@@ -1,11 +1,14 @@
/**
* Provides classes for performing local (intra-procedural) and
* global (inter-procedural) taint-tracking analyses.
* Provides a `TaintTracking2` module, which is a copy of the `TaintTracking`
* module. Use this class when data-flow configurations or taint-tracking
* configurations must depend on each other. Two classes extending
* `DataFlow::Configuration` should never depend on each other, but one of them
* should instead depend on a `DataFlow2::Configuration`, a
* `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. The
* `TaintTracking::Configuration` class extends `DataFlow::Configuration`, and
* `TaintTracking2::Configuration` extends `DataFlow2::Configuration`.
*
* We define _taint propagation_ informally to mean that a substantial part of
* the information from the source is preserved at the sink. For example, taint
* propagates from `x` to `x + 100`, but it does not propagate from `x` to `x >
* 100` since we consider a single bit of information to be too little.
* See `semmle.code.cpp.dataflow.TaintTracking` for the full documentation.
*/
module TaintTracking2 {
import semmle.code.cpp.dataflow.internal.tainttracking2.TaintTrackingImpl

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -363,6 +363,7 @@ private module ImplCommon {
newtype TReturnPosition =
TReturnPosition0(DataFlowCallable c, ReturnKind kind) { returnPosition(_, c, kind) }
}
import ImplCommon
pragma[noinline]
@@ -418,7 +419,6 @@ class CallContextReturn extends CallContext, TReturn {
/** A callable tagged with a relevant return kind. */
class ReturnPosition extends TReturnPosition0 {
private DataFlowCallable c;
private ReturnKind kind;
ReturnPosition() { this = TReturnPosition0(c, kind) }

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -496,6 +496,12 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
*/
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
/**
* Holds if data can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
/**
* Holds if the initial value of `v`, if it is a source, flows to `var`.
*/

View File

@@ -84,18 +84,28 @@ cached class FlowVar extends TFlowVar {
*
* In contrast to a normal "definition", which provides a new value for
* something, a partial definition is an expression that may affect a
* value, but does not necessarily replace it entirely. For example,
* `x.y = 1;` is a partial definition of the object `x`.
* value, but does not necessarily replace it entirely. For example:
* ```
* x.y = 1; // a partial definition of the object `x`.
* x.y.z = 1; // a partial definition of the objects `x` and `x.y`.
* x.setY(1); // a partial definition of the object `x`.
* setY(&x); // a partial definition of the object `x`.
* ```
*/
private module PartialDefinitions {
private newtype TPartialDefinition =
TExplicitFieldStoreQualifier(Expr qualifier, ControlFlowNode node) {
exists(FieldAccess fa |
isInstanceFieldWrite(fa, node) and qualifier = fa.getQualifier()
exists(FieldAccess fa | qualifier = fa.getQualifier() |
isInstanceFieldWrite(fa, node)
or
exists(PartialDefinition pd |
node = pd.getSubBasicBlockStart() and
fa = pd.getDefinedExpr()
)
)
} or
TExplicitCallQualifier(Expr qualifier, Call call) { qualifier = call.getQualifier() } or
TReferenceArgument(Expr arg, VariableAccess va) { definitionByReference(va, arg) }
TReferenceArgument(Expr arg, VariableAccess va) { referenceArgument(va, arg) }
private predicate isInstanceFieldWrite(FieldAccess fa, ControlFlowNode node) {
not fa.getTarget().isStatic() and
@@ -116,8 +126,19 @@ private module PartialDefinitions {
predicate partiallyDefinesThis(ThisExpr e) { definedExpr = e }
/**
* Gets the subBasicBlock where this `PartialDefinition` is defined.
*/
ControlFlowNode getSubBasicBlockStart() { result = node }
/**
* Gets the expression that is being partially defined. For example in the
* following code:
* ```
* x.y = 1;
* ```
* The expression `x` is being partially defined.
*/
Expr getDefinedExpr() { result = definedExpr }
Location getLocation() {
@@ -133,18 +154,48 @@ private module PartialDefinitions {
}
/**
* A partial definition that's a definition by reference (in the sense of the
* `definitionByReference` predicate).
* A partial definition that's a definition by reference.
*/
class DefinitionByReference extends PartialDefinition, TReferenceArgument {
VariableAccess va;
DefinitionByReference() { definitionByReference(va, definedExpr) }
DefinitionByReference() {
// `this` is not restricted in this charpred. That's because the full
// extent of this class includes the charpred of the superclass, which
// relates `this` to `definedExpr`, and `va` is functionally determined
// by `definedExpr`.
referenceArgument(va, definedExpr)
}
VariableAccess getVariableAccess() { result = va }
override predicate partiallyDefines(Variable v) { va = v.getAnAccess() }
}
private predicate referenceArgument(VariableAccess va, Expr argument) {
argument = any(Call c).getAnArgument() and
exists(Type argumentType |
argumentType = argument.getFullyConverted().getType().stripTopLevelSpecifiers()
|
argumentType instanceof ReferenceType and
not argumentType.(ReferenceType).getBaseType().isConst() and
va = argument
or
argumentType instanceof PointerType and
not argumentType.(PointerType).getBaseType().isConst() and
(
// f(variable)
va = argument
or
// f(&variable)
va = argument.(AddressOfExpr).getOperand()
or
// f(&array[0])
va.getType().getUnspecifiedType() instanceof ArrayType and
va = argument.(AddressOfExpr).getOperand().(ArrayExpr).getArrayBase()
)
)
}
}
import PartialDefinitions
private import FlowVar_internal
@@ -215,7 +266,7 @@ module FlowVar_internal {
not v instanceof Field and // Fields are interprocedural data flow, not local
reachable(sbb) and
(
initializer(sbb.getANode(), v, _)
initializer(v, sbb.getANode())
or
assignmentLikeOperation(sbb, v, _, _)
or
@@ -332,7 +383,12 @@ module FlowVar_internal {
assignmentLikeOperation(node, v, _, e) and
node = sbb
or
initializer(node, v, e) and
// We pick the defining `ControlFlowNode` of an `Initializer` to be its
// expression rather than the `Initializer` itself. That's because the
// `Initializer` of a `ConditionDeclExpr` is for historical reasons not
// part of the CFG and therefore ends up in the wrong basic block.
initializer(v, e) and
node = e and
node = sbb.getANode()
}
@@ -690,13 +746,11 @@ module FlowVar_internal {
}
/**
* Holds if `v` is initialized by `init` to have value `assignedExpr`.
* Holds if `v` is initialized to have value `assignedExpr`.
*/
predicate initializer(
Initializer init, LocalVariable v, Expr assignedExpr)
predicate initializer(LocalVariable v, Expr assignedExpr)
{
v = init.getDeclaration() and
assignedExpr = init.getExpr()
assignedExpr = v.getInitializer().getExpr()
}
/**

View File

@@ -80,6 +80,14 @@ predicate localTaint(DataFlow::Node source, DataFlow::Node sink) {
localTaintStep*(source, sink)
}
/**
* Holds if taint can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
predicate localExprTaint(Expr e1, Expr e2) {
localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
}
/**
* Holds if we do not propagate taint from `fromExpr` to `toExpr`
* even though `toExpr` is the AST parent of `fromExpr`.

View File

@@ -1,7 +1,9 @@
import semmle.code.cpp.Type
/** For upgraded databases without mangled name info. */
pragma[noinline]
private string getTopLevelClassName(@usertype c) {
not mangled_name(_, _) and
isClass(c) and
usertypes(c, result, _) and
not namespacembrs(_, c) and // not in a namespace
@@ -9,24 +11,76 @@ private string getTopLevelClassName(@usertype c) {
not class_instantiation(c, _) // not a template instantiation
}
/** Holds if `d` is a unique complete class named `name`. */
/**
* For upgraded databases without mangled name info.
* Holds if `d` is a unique complete class named `name`.
*/
pragma[noinline]
private predicate existsCompleteWithName(string name, @usertype d) {
not mangled_name(_, _) and
is_complete(d) and
name = getTopLevelClassName(d) and
onlyOneCompleteClassExistsWithName(name)
}
/** For upgraded databases without mangled name info. */
pragma[noinline]
private predicate onlyOneCompleteClassExistsWithName(string name) {
not mangled_name(_, _) and
strictcount(@usertype c | is_complete(c) and getTopLevelClassName(c) = name) = 1
}
/**
* For upgraded databases without mangled name info.
* Holds if `c` is an incomplete class named `name`.
*/
pragma[noinline]
private predicate existsIncompleteWithName(string name, @usertype c) {
not mangled_name(_, _) and
not is_complete(c) and
name = getTopLevelClassName(c)
}
/**
* For upgraded databases without mangled name info.
* Holds if `c` is an incomplete class, and there exists a unique complete class `d`
* with the same name.
*/
private predicate oldHasCompleteTwin(@usertype c, @usertype d) {
not mangled_name(_, _) and
exists(string name |
existsIncompleteWithName(name, c) and
existsCompleteWithName(name, d)
)
}
pragma[noinline]
private @mangledname getTopLevelClassMangledName(@usertype c) {
isClass(c) and
mangled_name(c, result) and
not namespacembrs(_, c) and // not in a namespace
not member(_, _, c) and // not in some structure
not class_instantiation(c, _) // not a template instantiation
}
/** Holds if `d` is a unique complete class named `name`. */
pragma[noinline]
private predicate existsCompleteWithMangledName(@mangledname name, @usertype d) {
is_complete(d) and
name = getTopLevelClassMangledName(d) and
onlyOneCompleteClassExistsWithMangledName(name)
}
pragma[noinline]
private predicate onlyOneCompleteClassExistsWithMangledName(@mangledname name) {
strictcount(@usertype c | is_complete(c) and getTopLevelClassMangledName(c) = name) = 1
}
/** Holds if `c` is an incomplete class named `name`. */
pragma[noinline]
private predicate existsIncompleteWithName(string name, @usertype c) {
private predicate existsIncompleteWithMangledName(@mangledname name, @usertype c) {
not is_complete(c) and
name = getTopLevelClassName(c)
name = getTopLevelClassMangledName(c)
}
/**
@@ -34,9 +88,9 @@ private predicate existsIncompleteWithName(string name, @usertype c) {
* with the same name.
*/
private predicate hasCompleteTwin(@usertype c, @usertype d) {
exists(string name |
existsIncompleteWithName(name, c) and
existsCompleteWithName(name, d)
exists(@mangledname name |
existsIncompleteWithMangledName(name, c) and
existsCompleteWithMangledName(name, d)
)
}
@@ -49,7 +103,11 @@ cached private module Cached {
cached @usertype resolveClass(@usertype c) {
hasCompleteTwin(c, result)
or
(not hasCompleteTwin(c, _) and result = c)
oldHasCompleteTwin(c, result)
or
(not hasCompleteTwin(c, _) and
not oldHasCompleteTwin(c, _) and
result = c)
}
/**

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -363,6 +363,7 @@ private module ImplCommon {
newtype TReturnPosition =
TReturnPosition0(DataFlowCallable c, ReturnKind kind) { returnPosition(_, c, kind) }
}
import ImplCommon
pragma[noinline]
@@ -418,7 +419,6 @@ class CallContextReturn extends CallContext, TReturn {
/** A callable tagged with a relevant return kind. */
class ReturnPosition extends TReturnPosition0 {
private DataFlowCallable c;
private ReturnKind kind;
ReturnPosition() { this = TReturnPosition0(c, kind) }

View File

@@ -178,6 +178,12 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
*/
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
/**
* Holds if data can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.
*/
predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) }
/**
* A guard that validates some expression.
*

View File

@@ -76,7 +76,6 @@ DefaultEdge defaultEdge() { result = TDefaultEdge() }
*/
class CaseEdge extends EdgeKind, TCaseEdge {
string minValue;
string maxValue;
CaseEdge() { this = TCaseEdge(minValue, maxValue) }

View File

@@ -59,7 +59,6 @@ abstract class IRVariable extends TIRVariable {
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() { this = TIRUserVariable(var, type, func) }
@@ -110,9 +109,7 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Language::AST ast;
TempVariableTag tag;
Language::Type type;
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }

View File

@@ -922,7 +922,6 @@ class ConvertInstruction extends UnaryInstruction {
*/
class InheritanceConversionInstruction extends UnaryInstruction {
Language::Class baseClass;
Language::Class derivedClass;
InheritanceConversionInstruction() {

View File

@@ -196,9 +196,7 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
@@ -231,7 +229,6 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
@@ -359,7 +356,6 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
@@ -413,11 +409,8 @@ class SideEffectOperand extends TypedOperand {
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }

View File

@@ -59,7 +59,6 @@ abstract class IRVariable extends TIRVariable {
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() { this = TIRUserVariable(var, type, func) }
@@ -110,9 +109,7 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Language::AST ast;
TempVariableTag tag;
Language::Type type;
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }

View File

@@ -922,7 +922,6 @@ class ConvertInstruction extends UnaryInstruction {
*/
class InheritanceConversionInstruction extends UnaryInstruction {
Language::Class baseClass;
Language::Class derivedClass;
InheritanceConversionInstruction() {

View File

@@ -196,9 +196,7 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
@@ -231,7 +229,6 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
@@ -359,7 +356,6 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
@@ -413,11 +409,8 @@ class SideEffectOperand extends TypedOperand {
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }

View File

@@ -59,7 +59,6 @@ abstract class IRVariable extends TIRVariable {
*/
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() { this = TIRUserVariable(var, type, func) }
@@ -110,9 +109,7 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Language::AST ast;
TempVariableTag tag;
Language::Type type;
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }

View File

@@ -922,7 +922,6 @@ class ConvertInstruction extends UnaryInstruction {
*/
class InheritanceConversionInstruction extends UnaryInstruction {
Language::Class baseClass;
Language::Class derivedClass;
InheritanceConversionInstruction() {

View File

@@ -196,9 +196,7 @@ class MemoryOperand extends Operand {
*/
class NonPhiOperand extends Operand {
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
@@ -231,7 +229,6 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
Overlap overlap;
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
@@ -359,7 +356,6 @@ class ThisArgumentOperand extends ArgumentOperand {
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() { argIndex = tag.getArgIndex() }
@@ -413,11 +409,8 @@ class SideEffectOperand extends TypedOperand {
*/
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
PhiInputOperand() { this = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap) }

View File

@@ -705,6 +705,11 @@ usertype_uuid(
unique string uuid: string ref
);
mangled_name(
unique int id: @declaration ref,
int mangled_name : @mangledname
);
is_pod_class(unique int id: @usertype ref);
is_standard_layout_class(unique int id: @usertype ref);

View File

@@ -116,6 +116,10 @@
<v>4328015</v>
</e>
<e>
<k>@mangledname</k>
<v>533074</v>
</e>
<e>
<k>@type_mention</k>
<v>1699398</v>
</e>
@@ -200,6 +204,22 @@
<v>1685056</v>
</e>
<e>
<k>@preincrexpr</k>
<v>63965</v>
</e>
<e>
<k>@predecrexpr</k>
<v>26590</v>
</e>
<e>
<k>@assignexpr</k>
<v>551713</v>
</e>
<e>
<k>@varaccess</k>
<v>5376523</v>
</e>
<e>
<k>@literal</k>
<v>4374193</v>
</e>
@@ -276,14 +296,6 @@
<v>5401</v>
</e>
<e>
<k>@preincrexpr</k>
<v>63965</v>
</e>
<e>
<k>@predecrexpr</k>
<v>26590</v>
</e>
<e>
<k>@conditionalexpr</k>
<v>154429</v>
</e>
@@ -396,10 +408,6 @@
<v>1</v>
</e>
<e>
<k>@assignexpr</k>
<v>551713</v>
</e>
<e>
<k>@assignaddexpr</k>
<v>68305</v>
</e>
@@ -488,10 +496,6 @@
<v>30</v>
</e>
<e>
<k>@varaccess</k>
<v>5376523</v>
</e>
<e>
<k>@thisaccess</k>
<v>1181367</v>
</e>
@@ -844,6 +848,14 @@
<v>1284491</v>
</e>
<e>
<k>@stmt_return</k>
<v>1197363</v>
</e>
<e>
<k>@stmt_block</k>
<v>1398476</v>
</e>
<e>
<k>@stmt_if</k>
<v>524558</v>
</e>
@@ -860,14 +872,6 @@
<v>85508</v>
</e>
<e>
<k>@stmt_return</k>
<v>1197363</v>
</e>
<e>
<k>@stmt_block</k>
<v>1398476</v>
</e>
<e>
<k>@stmt_end_test_while</k>
<v>149900</v>
</e>
@@ -936,14 +940,6 @@
<v>3</v>
</e>
<e>
<k>@ppd_plain_include</k>
<v>321760</v>
</e>
<e>
<k>@ppd_define</k>
<v>350005</v>
</e>
<e>
<k>@ppd_if</k>
<v>171105</v>
</e>
@@ -968,6 +964,14 @@
<v>329749</v>
</e>
<e>
<k>@ppd_plain_include</k>
<v>321760</v>
</e>
<e>
<k>@ppd_define</k>
<v>350005</v>
</e>
<e>
<k>@ppd_undef</k>
<v>21155</v>
</e>
@@ -1492,7 +1496,7 @@
</e>
<e>
<k>seconds</k>
<v>12182</v>
<v>12669</v>
</e>
</columnsizes>
<dependencies>
@@ -1536,14 +1540,19 @@
<budget>12</budget>
<bs>
<b>
<a>2</a>
<b>3</b>
<v>24</v>
</b>
<b>
<a>3</a>
<b>4</b>
<v>3149</v>
<v>3027</v>
</b>
<b>
<a>4</a>
<b>5</b>
<v>7416</v>
<v>7513</v>
</b>
</bs>
</hist>
@@ -1589,8 +1598,8 @@
<budget>12</budget>
<bs>
<b>
<a>1002</a>
<b>1003</b>
<a>1042</a>
<b>1043</b>
<v>12</v>
</b>
</bs>
@@ -1647,13 +1656,13 @@
<v>12</v>
</b>
<b>
<a>547</a>
<b>548</b>
<a>563</a>
<b>564</b>
<v>12</v>
</b>
<b>
<a>577</a>
<b>578</b>
<a>620</a>
<b>621</b>
<v>12</v>
</b>
</bs>
@@ -1670,28 +1679,23 @@
<b>
<a>1</a>
<b>2</b>
<v>7684</v>
<v>8036</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>2662</v>
<v>2711</v>
</b>
<b>
<a>3</a>
<b>4</b>
<v>814</v>
<v>996</v>
</b>
<b>
<a>4</a>
<b>14</b>
<b>597</b>
<v>924</v>
</b>
<b>
<a>14</a>
<b>616</b>
<v>97</v>
</b>
</bs>
</hist>
</val>
@@ -1706,7 +1710,7 @@
<b>
<a>1</a>
<b>2</b>
<v>12182</v>
<v>12669</v>
</b>
</bs>
</hist>
@@ -1722,17 +1726,17 @@
<b>
<a>1</a>
<b>2</b>
<v>10517</v>
<v>10796</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>1653</v>
<v>1835</v>
</b>
<b>
<a>3</a>
<b>4</b>
<v>12</v>
<v>36</v>
</b>
</bs>
</hist>
@@ -2111,11 +2115,11 @@
</e>
<e>
<k>cpu_seconds</k>
<v>8437</v>
<v>8450</v>
</e>
<e>
<k>elapsed_seconds</k>
<v>170</v>
<v>182</v>
</e>
</columnsizes>
<dependencies>
@@ -2161,17 +2165,17 @@
<b>
<a>1</a>
<b>2</b>
<v>7112</v>
<v>7064</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>911</v>
<v>984</v>
</b>
<b>
<a>3</a>
<b>9</b>
<v>413</v>
<v>401</v>
</b>
</bs>
</hist>
@@ -2192,7 +2196,7 @@
<b>
<a>2</a>
<b>3</b>
<v>486</v>
<v>498</v>
</b>
</bs>
</hist>
@@ -2208,7 +2212,7 @@
<b>
<a>1</a>
<b>2</b>
<v>24</v>
<v>36</v>
</b>
<b>
<a>2</a>
@@ -2216,38 +2220,48 @@
<v>24</v>
</b>
<b>
<a>3</a>
<b>4</b>
<a>4</a>
<b>5</b>
<v>12</v>
</b>
<b>
<a>9</a>
<b>10</b>
<a>10</a>
<b>11</b>
<v>12</v>
</b>
<b>
<a>11</a>
<b>12</b>
<a>12</a>
<b>13</b>
<v>12</v>
</b>
<b>
<a>21</a>
<b>22</b>
<v>24</v>
</b>
<b>
<a>45</a>
<b>46</b>
<a>18</a>
<b>19</b>
<v>12</v>
</b>
<b>
<a>129</a>
<b>130</b>
<a>23</a>
<b>24</b>
<v>12</v>
</b>
<b>
<a>133</a>
<b>134</b>
<a>57</a>
<b>58</b>
<v>12</v>
</b>
<b>
<a>127</a>
<b>128</b>
<v>12</v>
</b>
<b>
<a>131</a>
<b>132</b>
<v>12</v>
</b>
<b>
<a>237</a>
<b>238</b>
<v>12</v>
</b>
<b>
@@ -2255,11 +2269,6 @@
<b>246</b>
<v>12</v>
</b>
<b>
<a>248</a>
<b>249</b>
<v>12</v>
</b>
</bs>
</hist>
</val>
@@ -2274,7 +2283,7 @@
<b>
<a>1</a>
<b>2</b>
<v>24</v>
<v>36</v>
</b>
<b>
<a>2</a>
@@ -2282,48 +2291,53 @@
<v>24</v>
</b>
<b>
<a>3</a>
<b>4</b>
<a>4</a>
<b>5</b>
<v>12</v>
</b>
<b>
<a>9</a>
<b>10</b>
<a>10</a>
<b>11</b>
<v>12</v>
</b>
<b>
<a>11</a>
<b>12</b>
<a>12</a>
<b>13</b>
<v>12</v>
</b>
<b>
<a>21</a>
<b>22</b>
<v>24</v>
</b>
<b>
<a>45</a>
<b>46</b>
<a>17</a>
<b>18</b>
<v>12</v>
</b>
<b>
<a>107</a>
<b>108</b>
<a>23</a>
<b>24</b>
<v>12</v>
</b>
<b>
<a>119</a>
<b>120</b>
<a>54</a>
<b>55</b>
<v>12</v>
</b>
<b>
<a>177</a>
<b>178</b>
<a>105</a>
<b>106</b>
<v>12</v>
</b>
<b>
<a>215</a>
<b>216</b>
<a>114</a>
<b>115</b>
<v>12</v>
</b>
<b>
<a>168</a>
<b>169</b>
<v>12</v>
</b>
<b>
<a>222</a>
<b>223</b>
<v>12</v>
</b>
</bs>
@@ -23516,6 +23530,79 @@
</dependencies>
</relation>
<relation>
<name>mangled_name</name>
<cardinality>4326447</cardinality>
<columnsizes>
<e>
<k>id</k>
<v>4326447</v>
</e>
<e>
<k>mangled_name</k>
<v>533074</v>
</e>
</columnsizes>
<dependencies>
<dep>
<src>id</src>
<trg>mangled_name</trg>
<val>
<hist>
<budget>12</budget>
<bs>
<b>
<a>1</a>
<b>2</b>
<v>4326447</v>
</b>
</bs>
</hist>
</val>
</dep>
<dep>
<src>mangled_name</src>
<trg>id</trg>
<val>
<hist>
<budget>12</budget>
<bs>
<b>
<a>1</a>
<b>2</b>
<v>326831</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>67771</v>
</b>
<b>
<a>3</a>
<b>4</b>
<v>35794</v>
</b>
<b>
<a>4</a>
<b>8</b>
<v>44998</v>
</b>
<b>
<a>8</a>
<b>36</b>
<v>40183</v>
</b>
<b>
<a>36</a>
<b>8470</b>
<v>17495</v>
</b>
</bs>
</hist>
</val>
</dep>
</dependencies>
</relation>
<relation>
<name>is_pod_class</name>
<cardinality>1041528</cardinality>
<columnsizes>
@@ -32123,11 +32210,11 @@
</e>
<e>
<k>kind</k>
<v>1167</v>
<v>393</v>
</e>
<e>
<k>location</k>
<v>3937292</v>
<v>6150603</v>
</e>
</columnsizes>
<dependencies>
@@ -32171,69 +32258,69 @@
<budget>12</budget>
<bs>
<b>
<a>4</a>
<b>18</b>
<v>97</v>
<a>5</a>
<b>28</b>
<v>30</v>
</b>
<b>
<a>22</a>
<b>48</b>
<v>85</v>
<a>71</a>
<b>82</b>
<v>30</v>
</b>
<b>
<a>48</a>
<b>91</b>
<v>97</v>
<a>94</a>
<b>255</b>
<v>30</v>
</b>
<b>
<a>123</a>
<b>295</b>
<v>97</v>
<a>271</a>
<b>627</b>
<v>30</v>
</b>
<b>
<a>341</a>
<b>541</b>
<v>97</v>
<a>858</a>
<b>1879</b>
<v>30</v>
</b>
<b>
<a>541</a>
<b>883</b>
<v>97</v>
<a>2191</a>
<b>3716</b>
<v>30</v>
</b>
<b>
<a>1163</a>
<b>2188</b>
<v>97</v>
<a>4305</a>
<b>6068</b>
<v>30</v>
</b>
<b>
<a>2428</a>
<b>3029</b>
<v>97</v>
<a>7004</a>
<b>11661</b>
<v>30</v>
</b>
<b>
<a>3265</a>
<b>4616</b>
<v>97</v>
<a>12107</a>
<b>20202</b>
<v>30</v>
</b>
<b>
<a>4933</a>
<b>6580</b>
<v>97</v>
<a>21965</a>
<b>29561</b>
<v>30</v>
</b>
<b>
<a>6933</a>
<b>20444</b>
<v>97</v>
<a>32830</a>
<b>41032</b>
<v>30</v>
</b>
<b>
<a>30541</a>
<b>198015</b>
<v>97</v>
<a>44670</a>
<b>145995</b>
<v>30</v>
</b>
<b>
<a>399017</a>
<b>399018</b>
<v>12</v>
<a>447805</a>
<b>725766</b>
<v>24</v>
</b>
</bs>
</hist>
@@ -32248,63 +32335,68 @@
<bs>
<b>
<a>1</a>
<b>7</b>
<v>97</v>
<b>24</b>
<v>30</v>
</b>
<b>
<a>7</a>
<b>14</b>
<v>97</v>
<a>27</a>
<b>72</b>
<v>30</v>
</b>
<b>
<a>15</a>
<b>28</b>
<v>97</v>
<a>77</a>
<b>157</b>
<v>30</v>
</b>
<b>
<a>29</a>
<b>47</b>
<v>97</v>
<a>171</a>
<b>402</b>
<v>30</v>
</b>
<b>
<a>74</a>
<b>171</b>
<v>97</v>
<a>422</a>
<b>1083</b>
<v>30</v>
</b>
<b>
<a>175</a>
<b>325</b>
<v>97</v>
<a>1179</a>
<b>1862</b>
<v>30</v>
</b>
<b>
<a>371</a>
<b>515</b>
<v>97</v>
<a>2201</a>
<b>4268</b>
<v>30</v>
</b>
<b>
<a>623</a>
<b>1087</b>
<v>97</v>
<a>4679</a>
<b>6584</b>
<v>30</v>
</b>
<b>
<a>1127</a>
<b>1577</b>
<v>97</v>
<a>6624</a>
<b>11083</b>
<v>30</v>
</b>
<b>
<a>1827</a>
<b>2138</b>
<v>97</v>
<a>11359</a>
<b>12983</b>
<v>30</v>
</b>
<b>
<a>2219</a>
<b>8862</b>
<v>97</v>
<a>17158</a>
<b>28621</b>
<v>30</v>
</b>
<b>
<a>9363</a>
<b>117436</b>
<v>97</v>
<a>29980</a>
<b>88945</b>
<v>30</v>
</b>
<b>
<a>128315</a>
<b>425042</b>
<v>24</v>
</b>
</bs>
</hist>
@@ -32320,37 +32412,22 @@
<b>
<a>1</a>
<b>2</b>
<v>1896838</v>
<v>4450587</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>762528</v>
<v>874643</v>
</b>
<b>
<a>3</a>
<b>4</b>
<v>367780</v>
<b>6</b>
<v>496205</v>
</b>
<b>
<a>4</a>
<b>5</b>
<v>283559</v>
</b>
<b>
<a>5</a>
<b>9</b>
<v>309310</v>
</b>
<b>
<a>9</a>
<b>73</b>
<v>295656</v>
</b>
<b>
<a>73</a>
<b>110845</b>
<v>21617</v>
<a>6</a>
<b>22445</b>
<v>329167</v>
</b>
</bs>
</hist>
@@ -32366,17 +32443,22 @@
<b>
<a>1</a>
<b>2</b>
<v>2811371</v>
<v>4599301</v>
</b>
<b>
<a>2</a>
<b>3</b>
<v>875346</v>
<v>812812</v>
</b>
<b>
<a>3</a>
<b>30</b>
<v>250573</v>
<b>5</b>
<v>498909</v>
</b>
<b>
<a>5</a>
<b>33</b>
<v>239579</v>
</b>
</bs>
</hist>

View File

@@ -0,0 +1,53 @@
// semmle-extractor-options: --edg --clang
int source();
void sink(int); void sink(const int *); void sink(int **);
struct twoIntFields {
int m1, m2;
int getFirst() { return m1; }
};
void following_pointers(
int sourceArray1[],
int cleanArray1[],
twoIntFields sourceStruct1,
twoIntFields *sourceStruct1_ptr,
int (*sourceFunctionPointer)())
{
sink(sourceArray1); // flow
sink(sourceArray1[0]); // no flow
sink(*sourceArray1); // no flow
sink(&sourceArray1); // no flow (since sourceArray1 is really a pointer)
sink(sourceStruct1.m1); // no flow
sink(sourceStruct1_ptr->m1); // no flow
sink(sourceStruct1_ptr->getFirst()); // no flow
sourceStruct1_ptr->m1 = source();
sink(sourceStruct1_ptr->m1); // flow
sink(sourceStruct1_ptr->getFirst()); // flow [NOT DETECTED with IR]
sink(sourceStruct1_ptr->m2); // no flow
sink(sourceStruct1.m1); // no flow
twoIntFields s = { source(), source() };
sink(s.m2); // flow
twoIntFields sArray[1] = { { source(), source() } };
// TODO: fix this like above
sink(sArray[0].m2); // flow (AST dataflow misses this due to limitations of the analysis)
twoIntFields sSwapped = { .m2 = source(), .m1 = 0 };
sink(sSwapped.m2); // flow
sink(sourceFunctionPointer()); // no flow
int stackArray[2] = { source(), source() };
stackArray[0] = source();
sink(stackArray); // no flow
}

View File

@@ -37,25 +37,25 @@
| test.cpp:24:10:24:11 | t2 | test.cpp:23:23:23:24 | t1 |
| test.cpp:24:10:24:11 | t2 | test.cpp:24:5:24:11 | ... = ... |
| test.cpp:24:10:24:11 | t2 | test.cpp:26:8:26:9 | t1 |
| test.cpp:430:48:430:54 | source1 | test.cpp:432:17:432:23 | source1 |
| test.cpp:431:12:431:13 | 0 | test.cpp:432:11:432:13 | tmp |
| test.cpp:431:12:431:13 | 0 | test.cpp:432:33:432:35 | tmp |
| test.cpp:431:12:431:13 | 0 | test.cpp:433:8:433:10 | tmp |
| test.cpp:432:10:432:13 | & ... | test.cpp:432:3:432:8 | call to memcpy |
| test.cpp:432:10:432:13 | ref arg & ... | test.cpp:432:3:432:8 | call to memcpy |
| test.cpp:432:10:432:13 | ref arg & ... | test.cpp:432:33:432:35 | tmp |
| test.cpp:432:10:432:13 | ref arg & ... | test.cpp:433:8:433:10 | tmp |
| test.cpp:432:17:432:23 | source1 | test.cpp:432:10:432:13 | ref arg & ... |
| test.cpp:436:53:436:59 | source1 | test.cpp:439:17:439:23 | source1 |
| test.cpp:436:66:436:66 | b | test.cpp:441:7:441:7 | b |
| test.cpp:437:12:437:13 | 0 | test.cpp:438:19:438:21 | tmp |
| test.cpp:437:12:437:13 | 0 | test.cpp:439:11:439:13 | tmp |
| test.cpp:437:12:437:13 | 0 | test.cpp:439:33:439:35 | tmp |
| test.cpp:437:12:437:13 | 0 | test.cpp:440:8:440:10 | tmp |
| test.cpp:437:12:437:13 | 0 | test.cpp:442:10:442:12 | tmp |
| test.cpp:439:10:439:13 | & ... | test.cpp:439:3:439:8 | call to memcpy |
| test.cpp:439:10:439:13 | ref arg & ... | test.cpp:439:3:439:8 | call to memcpy |
| test.cpp:439:10:439:13 | ref arg & ... | test.cpp:439:33:439:35 | tmp |
| test.cpp:439:10:439:13 | ref arg & ... | test.cpp:440:8:440:10 | tmp |
| test.cpp:439:10:439:13 | ref arg & ... | test.cpp:442:10:442:12 | tmp |
| test.cpp:439:17:439:23 | source1 | test.cpp:439:10:439:13 | ref arg & ... |
| test.cpp:382:48:382:54 | source1 | test.cpp:384:17:384:23 | source1 |
| test.cpp:383:12:383:13 | 0 | test.cpp:384:11:384:13 | tmp |
| test.cpp:383:12:383:13 | 0 | test.cpp:384:33:384:35 | tmp |
| test.cpp:383:12:383:13 | 0 | test.cpp:385:8:385:10 | tmp |
| test.cpp:384:10:384:13 | & ... | test.cpp:384:3:384:8 | call to memcpy |
| test.cpp:384:10:384:13 | ref arg & ... | test.cpp:384:3:384:8 | call to memcpy |
| test.cpp:384:10:384:13 | ref arg & ... | test.cpp:384:33:384:35 | tmp |
| test.cpp:384:10:384:13 | ref arg & ... | test.cpp:385:8:385:10 | tmp |
| test.cpp:384:17:384:23 | source1 | test.cpp:384:10:384:13 | ref arg & ... |
| test.cpp:388:53:388:59 | source1 | test.cpp:391:17:391:23 | source1 |
| test.cpp:388:66:388:66 | b | test.cpp:393:7:393:7 | b |
| test.cpp:389:12:389:13 | 0 | test.cpp:390:19:390:21 | tmp |
| test.cpp:389:12:389:13 | 0 | test.cpp:391:11:391:13 | tmp |
| test.cpp:389:12:389:13 | 0 | test.cpp:391:33:391:35 | tmp |
| test.cpp:389:12:389:13 | 0 | test.cpp:392:8:392:10 | tmp |
| test.cpp:389:12:389:13 | 0 | test.cpp:394:10:394:12 | tmp |
| test.cpp:391:10:391:13 | & ... | test.cpp:391:3:391:8 | call to memcpy |
| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:391:3:391:8 | call to memcpy |
| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:391:33:391:35 | tmp |
| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:392:8:392:10 | tmp |
| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:394:10:394:12 | tmp |
| test.cpp:391:17:391:23 | source1 | test.cpp:391:10:391:13 | ref arg & ... |

View File

@@ -111,54 +111,6 @@ void local_references(int &source1, int clean1) {
}
}
struct twoIntFields {
int m1, m2;
int getFirst() { return m1; }
};
void following_pointers(
int sourceArray1[],
int cleanArray1[],
twoIntFields sourceStruct1,
twoIntFields *sourceStruct1_ptr,
int (*sourceFunctionPointer)())
{
sink(sourceArray1); // flow
sink(sourceArray1[0]); // no flow
sink(*sourceArray1); // no flow
sink(&sourceArray1); // no flow (since sourceArray1 is really a pointer)
sink(sourceStruct1.m1); // no flow
sink(sourceStruct1_ptr->m1); // no flow
sink(sourceStruct1_ptr->getFirst()); // no flow
sourceStruct1_ptr->m1 = source();
sink(sourceStruct1_ptr->m1); // flow
sink(sourceStruct1_ptr->getFirst()); // flow [NOT DETECTED with IR]
sink(sourceStruct1_ptr->m2); // no flow
sink(sourceStruct1.m1); // no flow
twoIntFields s = { source(), source() };
sink(s.m2); // flow
twoIntFields sArray[1] = { { source(), source() } };
// TODO: fix this like above
sink(sArray[0].m2); // flow (AST dataflow misses this due to limitations of the analysis)
twoIntFields sSwapped = { .m2 = source(), .m1 = 0 };
sink(sSwapped.m2); // flow
sink(sourceFunctionPointer()); // no flow
int stackArray[2] = { source(), source() };
stackArray[0] = source();
sink(stackArray); // no flow
}
int alwaysAssignSource(int *out) {
*out = source();
return 0;

View File

@@ -1,4 +1,9 @@
| acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source |
| 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:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | 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:21:3:21:6 | t | lambdas.cpp:8:10:8:15 | call to source |
@@ -19,42 +24,37 @@
| test.cpp:86:8:86:9 | i1 | test.cpp:83:7:83:8 | u2 |
| test.cpp:90:8:90:14 | source1 | test.cpp:89:28:89:34 | source1 |
| test.cpp:103:10:103:12 | ref | test.cpp:100:13:100:18 | call to source |
| test.cpp:126:8:126:19 | sourceArray1 | test.cpp:120:9:120:20 | sourceArray1 |
| test.cpp:137:27:137:28 | m1 | test.cpp:136:27:136:32 | call to source |
| test.cpp:138:27:138:34 | call to getFirst | test.cpp:136:27:136:32 | call to source |
| test.cpp:145:10:145:11 | m2 | test.cpp:142:32:142:37 | call to source |
| test.cpp:153:17:153:18 | m2 | test.cpp:151:35:151:40 | call to source |
| test.cpp:188:8:188:8 | y | test.cpp:186:27:186:32 | call to source |
| test.cpp:192:8:192:8 | s | test.cpp:199:33:199:38 | call to source |
| test.cpp:200:8:200:8 | y | test.cpp:199:33:199:38 | call to source |
| test.cpp:205:8:205:8 | x | test.cpp:212:34:212:39 | call to source |
| test.cpp:213:8:213:8 | y | test.cpp:212:34:212:39 | call to source |
| test.cpp:226:8:226:8 | y | test.cpp:219:11:219:16 | call to source |
| test.cpp:308:12:308:12 | x | test.cpp:293:14:293:19 | call to source |
| test.cpp:314:12:314:12 | x | test.cpp:313:22:313:27 | call to source |
| test.cpp:337:14:337:14 | x | test.cpp:353:17:353:22 | call to source |
| test.cpp:366:7:366:7 | x | test.cpp:362:4:362:9 | call to source |
| test.cpp:397:10:397:18 | globalVar | test.cpp:395:17:395:22 | call to source |
| test.cpp:413:10:413:14 | field | test.cpp:407:13:407:18 | call to source |
| test.cpp:417:10:417:14 | field | test.cpp:421:13:421:18 | call to source |
| test.cpp:423:10:423:14 | field | test.cpp:421:13:421:18 | call to source |
| test.cpp:433:8:433:10 | tmp | test.cpp:430:48:430:54 | source1 |
| test.cpp:440:8:440:10 | tmp | test.cpp:436:53:436:59 | source1 |
| test.cpp:442:10:442:12 | tmp | test.cpp:436:53:436:59 | source1 |
| test.cpp:449:8:449:10 | tmp | test.cpp:447:7:447:9 | tmp |
| test.cpp:456:8:456:10 | tmp | test.cpp:453:7:453:9 | tmp |
| test.cpp:466:8:466:12 | local | test.cpp:464:7:464:11 | local |
| test.cpp:466:8:466:12 | local | test.cpp:465:16:465:20 | ref arg local |
| test.cpp:472:8:472:12 | local | test.cpp:470:7:470:11 | local |
| test.cpp:472:8:472:12 | local | test.cpp:471:20:471:25 | ref arg & ... |
| test.cpp:478:8:478:12 | local | test.cpp:476:7:476:11 | local |
| test.cpp:478:8:478:12 | local | test.cpp:477:20:477:24 | ref arg local |
| test.cpp:485:8:485:12 | local | test.cpp:483:7:483:11 | local |
| test.cpp:485:8:485:12 | local | test.cpp:484:18:484:23 | ref arg & ... |
| test.cpp:491:8:491:12 | local | test.cpp:489:7:489:11 | local |
| test.cpp:491:8:491:12 | local | test.cpp:490:18:490:22 | ref arg local |
| test.cpp:498:9:498:22 | (statement expression) | test.cpp:497:26:497:32 | source1 |
| test.cpp:509:8:509:12 | local | test.cpp:497:26:497:32 | source1 |
| test.cpp:140:8:140:8 | y | test.cpp:138:27:138:32 | call to source |
| test.cpp:144:8:144:8 | s | test.cpp:151:33:151:38 | call to source |
| test.cpp:152:8:152:8 | y | test.cpp:151:33:151:38 | call to source |
| test.cpp:157:8:157:8 | x | test.cpp:164:34:164:39 | call to source |
| test.cpp:165:8:165:8 | y | test.cpp:164:34:164:39 | call to source |
| test.cpp:178:8:178:8 | y | test.cpp:171:11:171:16 | call to source |
| test.cpp:260:12:260:12 | x | test.cpp:245:14:245:19 | call to source |
| test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source |
| test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source |
| test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source |
| test.cpp:349:10:349:18 | globalVar | test.cpp:347:17:347:22 | call to source |
| test.cpp:365:10:365:14 | field | test.cpp:359:13:359:18 | 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 |
| test.cpp:394:10:394:12 | tmp | test.cpp:388:53:388:59 | source1 |
| test.cpp:401:8:401:10 | tmp | test.cpp:399:7:399:9 | tmp |
| test.cpp:408:8:408:10 | tmp | test.cpp:405:7:405:9 | tmp |
| test.cpp:418:8:418:12 | local | test.cpp:416:7:416:11 | local |
| test.cpp:418:8:418:12 | local | test.cpp:417:16:417:20 | ref arg local |
| test.cpp:424:8:424:12 | local | test.cpp:422:7:422:11 | local |
| test.cpp:424:8:424:12 | local | test.cpp:423:20:423:25 | ref arg & ... |
| test.cpp:430:8:430:12 | local | test.cpp:428:7:428:11 | local |
| test.cpp:430:8:430:12 | local | test.cpp:429:20:429:24 | ref arg local |
| test.cpp:437:8:437:12 | local | test.cpp:435:7:435:11 | local |
| test.cpp:437:8:437:12 | local | test.cpp:436:18:436:23 | ref arg & ... |
| test.cpp:443:8:443:12 | local | test.cpp:441:7:441:11 | local |
| test.cpp:443:8:443:12 | local | test.cpp:442:18:442:22 | ref arg local |
| test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 |
| test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 |
| true_upon_entry.cpp:21:8:21:8 | x | true_upon_entry.cpp:17:11:17:16 | call to source |
| true_upon_entry.cpp:29:8:29:8 | x | true_upon_entry.cpp:27:9:27:14 | call to source |
| true_upon_entry.cpp:39:8:39:8 | x | true_upon_entry.cpp:33:11:33:16 | call to source |

View File

@@ -1,3 +1,6 @@
| clang.cpp:28:27:28:32 | clang.cpp:29:27:29:28 | 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 |
| 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 |
@@ -7,28 +10,25 @@
| test.cpp:89:28:89:34 | test.cpp:92:8:92:14 | IR only |
| test.cpp:100:13:100:18 | test.cpp:103:10:103:12 | AST only |
| test.cpp:109:9:109:14 | test.cpp:110:10:110:12 | IR only |
| test.cpp:136:27:136:32 | test.cpp:137:27:137:28 | AST only |
| test.cpp:136:27:136:32 | test.cpp:138:27:138:34 | AST only |
| test.cpp:147:42:147:47 | test.cpp:149:18:149:19 | IR only |
| test.cpp:395:17:395:22 | test.cpp:397:10:397:18 | AST only |
| test.cpp:407:13:407:18 | test.cpp:413:10:413:14 | AST only |
| test.cpp:421:13:421:18 | test.cpp:417:10:417:14 | AST only |
| test.cpp:421:13:421:18 | test.cpp:423:10:423:14 | AST only |
| test.cpp:430:48:430:54 | test.cpp:433:8:433:10 | AST only |
| test.cpp:436:53:436:59 | test.cpp:440:8:440:10 | AST only |
| test.cpp:436:53:436:59 | test.cpp:442:10:442:12 | AST only |
| test.cpp:447:7:447:9 | test.cpp:449:8:449:10 | AST only |
| test.cpp:453:7:453:9 | test.cpp:456:8:456:10 | AST only |
| test.cpp:464:7:464:11 | test.cpp:466:8:466:12 | AST only |
| test.cpp:465:16:465:20 | test.cpp:466:8:466:12 | AST only |
| test.cpp:470:7:470:11 | test.cpp:472:8:472:12 | AST only |
| test.cpp:471:20:471:25 | test.cpp:472:8:472:12 | AST only |
| test.cpp:476:7:476:11 | test.cpp:478:8:478:12 | AST only |
| test.cpp:477:20:477:24 | test.cpp:478:8:478:12 | AST only |
| test.cpp:483:7:483:11 | test.cpp:485:8:485:12 | AST only |
| test.cpp:484:18:484:23 | test.cpp:485:8:485:12 | AST only |
| test.cpp:489:7:489:11 | test.cpp:491:8:491:12 | AST only |
| test.cpp:490:18:490:22 | test.cpp:491:8:491:12 | AST 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:373:13:373:18 | test.cpp:375:10:375:14 | AST only |
| test.cpp:382:48:382:54 | test.cpp:385:8:385:10 | AST only |
| test.cpp:388:53:388:59 | test.cpp:392:8:392:10 | AST only |
| test.cpp:388:53:388:59 | test.cpp:394:10:394:12 | 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 |
| test.cpp:417:16:417:20 | test.cpp:418:8:418:12 | AST only |
| test.cpp:422:7:422:11 | test.cpp:424:8:424:12 | AST only |
| test.cpp:423:20:423:25 | test.cpp:424:8:424:12 | AST only |
| test.cpp:428:7:428:11 | test.cpp:430:8:430:12 | AST only |
| test.cpp:429:20:429:24 | test.cpp:430:8:430:12 | AST only |
| test.cpp:435:7:435:11 | test.cpp:437:8:437:12 | AST only |
| test.cpp:436:18:436:23 | test.cpp:437:8:437:12 | AST only |
| test.cpp:441:7:441:11 | test.cpp:443:8:443:12 | AST only |
| test.cpp:442:18:442:22 | test.cpp:443:8:443:12 | AST only |
| true_upon_entry.cpp:9:11:9:16 | true_upon_entry.cpp:13:8:13:8 | IR only |
| true_upon_entry.cpp:62:11:62:16 | true_upon_entry.cpp:66:8:66:8 | IR only |
| true_upon_entry.cpp:98:11:98:16 | true_upon_entry.cpp:105:8:105:8 | IR only |

View File

@@ -1,5 +1,10 @@
| acrossLinkTargets.cpp:12:8:12:8 | Convert: (int)... | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source |
| acrossLinkTargets.cpp:12:8:12:8 | Load: x | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source |
| clang.cpp:18:8:18:19 | Convert: (const int *)... | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 |
| clang.cpp:18:8:18:19 | Load: sourceArray1 | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 |
| clang.cpp:37:10:37:11 | Load: m2 | clang.cpp:34:32:34:37 | Call: call to source |
| clang.cpp:41:18:41:19 | Load: m2 | clang.cpp:39:42:39:47 | Call: call to source |
| clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source |
| test.cpp:7:8:7:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:9:8:9:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:10:8:10:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source |
@@ -15,23 +20,18 @@
| test.cpp:90:8:90:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 |
| test.cpp:92:8:92:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 |
| test.cpp:110:10:110:12 | Load: (reference dereference) | test.cpp:109:9:109:14 | Call: call to source |
| test.cpp:126:8:126:19 | Convert: (const int *)... | test.cpp:120:9:120:20 | InitializeParameter: sourceArray1 |
| test.cpp:126:8:126:19 | Load: sourceArray1 | test.cpp:120:9:120:20 | InitializeParameter: sourceArray1 |
| test.cpp:145:10:145:11 | Load: m2 | test.cpp:142:32:142:37 | Call: call to source |
| test.cpp:149:18:149:19 | Load: m2 | test.cpp:147:42:147:47 | Call: call to source |
| test.cpp:153:17:153:18 | Load: m2 | test.cpp:151:35:151:40 | Call: call to source |
| test.cpp:188:8:188:8 | Load: y | test.cpp:186:27:186:32 | Call: call to source |
| test.cpp:192:8:192:8 | Load: s | test.cpp:199:33:199:38 | Call: call to source |
| test.cpp:200:8:200:8 | Load: y | test.cpp:199:33:199:38 | Call: call to source |
| test.cpp:205:8:205:8 | Load: x | test.cpp:212:34:212:39 | Call: call to source |
| test.cpp:213:8:213:8 | Load: y | test.cpp:212:34:212:39 | Call: call to source |
| test.cpp:226:8:226:8 | Load: y | test.cpp:219:11:219:16 | Call: call to source |
| test.cpp:308:12:308:12 | Load: x | test.cpp:293:14:293:19 | Call: call to source |
| test.cpp:314:12:314:12 | Load: x | test.cpp:313:22:313:27 | Call: call to source |
| test.cpp:337:14:337:14 | Load: x | test.cpp:353:17:353:22 | Call: call to source |
| test.cpp:366:7:366:7 | Load: x | test.cpp:362:4:362:9 | Call: call to source |
| test.cpp:498:9:498:22 | CopyValue: (statement expression) | test.cpp:497:26:497:32 | InitializeParameter: source1 |
| test.cpp:509:8:509:12 | Load: local | test.cpp:497:26:497:32 | InitializeParameter: source1 |
| test.cpp:140:8:140:8 | Load: y | test.cpp:138:27:138:32 | Call: call to source |
| test.cpp:144:8:144:8 | Load: s | test.cpp:151:33:151:38 | Call: call to source |
| test.cpp:152:8:152:8 | Load: y | test.cpp:151:33:151:38 | Call: call to source |
| test.cpp:157:8:157:8 | Load: x | test.cpp:164:34:164:39 | Call: call to source |
| test.cpp:165:8:165:8 | Load: y | test.cpp:164:34:164:39 | Call: call to source |
| test.cpp:178:8:178:8 | Load: y | test.cpp:171:11:171:16 | Call: call to source |
| test.cpp:260:12:260:12 | Load: x | test.cpp:245:14:245:19 | Call: call to source |
| test.cpp:266:12:266:12 | Load: x | test.cpp:265:22:265:27 | Call: call to source |
| test.cpp:289:14:289:14 | Load: x | test.cpp:305:17:305:22 | Call: call to source |
| test.cpp:318:7:318:7 | Load: x | test.cpp:314:4:314:9 | Call: call to source |
| test.cpp:450:9:450:22 | CopyValue: (statement expression) | test.cpp:449:26:449:32 | InitializeParameter: source1 |
| test.cpp:461:8:461:12 | Load: local | test.cpp:449:26:449:32 | InitializeParameter: source1 |
| true_upon_entry.cpp:13:8:13:8 | Load: x | true_upon_entry.cpp:9:11:9:16 | Call: call to source |
| true_upon_entry.cpp:21:8:21:8 | Load: x | true_upon_entry.cpp:17:11:17:16 | Call: call to source |
| true_upon_entry.cpp:29:8:29:8 | Load: x | true_upon_entry.cpp:27:9:27:14 | Call: call to source |

View File

@@ -1,20 +1,20 @@
| test.cpp:75:7:75:8 | u1 | test.cpp:76:8:76:9 | u1 |
| test.cpp:83:7:83:8 | u2 | test.cpp:84:13:84:14 | u2 |
| test.cpp:83:7:83:8 | u2 | test.cpp:85:8:85:9 | u2 |
| test.cpp:447:7:447:9 | tmp | test.cpp:448:11:448:13 | tmp |
| test.cpp:447:7:447:9 | tmp | test.cpp:449:8:449:10 | tmp |
| test.cpp:453:7:453:9 | tmp | test.cpp:454:19:454:21 | tmp |
| test.cpp:453:7:453:9 | tmp | test.cpp:455:11:455:13 | tmp |
| test.cpp:453:7:453:9 | tmp | test.cpp:456:8:456:10 | tmp |
| test.cpp:464:7:464:11 | local | test.cpp:465:16:465:20 | local |
| test.cpp:464:7:464:11 | local | test.cpp:466:8:466:12 | local |
| test.cpp:470:7:470:11 | local | test.cpp:471:21:471:25 | local |
| test.cpp:470:7:470:11 | local | test.cpp:472:8:472:12 | local |
| test.cpp:476:7:476:11 | local | test.cpp:477:20:477:24 | local |
| test.cpp:476:7:476:11 | local | test.cpp:478:8:478:12 | local |
| test.cpp:476:7:476:11 | local | test.cpp:479:9:479:13 | local |
| test.cpp:483:7:483:11 | local | test.cpp:484:19:484:23 | local |
| test.cpp:483:7:483:11 | local | test.cpp:485:8:485:12 | local |
| test.cpp:489:7:489:11 | local | test.cpp:490:18:490:22 | local |
| test.cpp:489:7:489:11 | local | test.cpp:491:8:491:12 | local |
| test.cpp:489:7:489:11 | local | test.cpp:492:9:492:13 | local |
| test.cpp:399:7:399:9 | tmp | test.cpp:400:11:400:13 | tmp |
| test.cpp:399:7:399:9 | tmp | test.cpp:401:8:401:10 | tmp |
| test.cpp:405:7:405:9 | tmp | test.cpp:406:19:406:21 | tmp |
| test.cpp:405:7:405:9 | tmp | test.cpp:407:11:407:13 | tmp |
| test.cpp:405:7:405:9 | tmp | test.cpp:408:8:408:10 | tmp |
| test.cpp:416:7:416:11 | local | test.cpp:417:16:417:20 | local |
| test.cpp:416:7:416:11 | local | test.cpp:418:8:418:12 | local |
| test.cpp:422:7:422:11 | local | test.cpp:423:21:423:25 | local |
| test.cpp:422:7:422:11 | local | test.cpp:424:8:424:12 | local |
| test.cpp:428:7:428:11 | local | test.cpp:429:20:429:24 | local |
| test.cpp:428:7:428:11 | local | test.cpp:430:8:430:12 | local |
| test.cpp:428:7:428:11 | local | test.cpp:431:9:431:13 | local |
| test.cpp:435:7:435:11 | local | test.cpp:436:19:436:23 | local |
| test.cpp:435:7:435:11 | local | test.cpp:437:8:437:12 | local |
| test.cpp:441:7:441:11 | local | test.cpp:442:18:442:22 | local |
| test.cpp:441:7:441:11 | local | test.cpp:443:8:443:12 | local |
| test.cpp:441:7:441:11 | local | test.cpp:444:9:444:13 | local |

View File

@@ -129,7 +129,7 @@ public:
{
B *b = new B();
f7(b);
sink(b->c); // flow [NOT DETECTED]
sink(b->c); // flow
}
class D
@@ -151,7 +151,7 @@ public:
D *d = new D(b, r());
sink(d->b); // flow x2
sink(d->b->c); // flow
sink(b->c); // flow [NOT DETECTED]
sink(b->c); // flow
}
void f10()

View File

@@ -61,3 +61,34 @@ void assignBeforeCopy() {
S copy2 = s2;
sink(copy2.m1); // flow
}
struct Wrapper {
S s;
};
void copyIntermediate() {
Wrapper w = { { 0, 0 } };
S s = w.s;
s.m1 = user_input();
sink(w.s.m1); // no flow
}
void pointerIntermediate() {
Wrapper w = { { 0, 0 } };
S *s = &w.s;
s->m1 = user_input();
sink(w.s.m1); // flow [FALSE NEGATIVE]
}
void referenceIntermediate() {
Wrapper w = { { 0, 0 } };
S &s = w.s;
s.m1 = user_input();
sink(w.s.m1); // flow [FALSE NEGATIVE]
}
void nestedAssign() {
Wrapper w = { { 0, 0 } };
w.s.m1 = user_input();
sink(w.s.m1); // flow
}

View File

@@ -33,8 +33,16 @@ void sink(int x)
void bar(Bar &b)
{
sink(b.f.a()); // flow (through `b1.f.setA` and `b3.f.setA`) [NOT DETECTED]
sink(b.f.b()); // flow (through `b2.f.setB` and `b3.f.setB`) [NOT DETECTED]
// The library correctly finds that the four `user_input` sources can make it
// to the `sink` calls, but it also finds some source/sink combinations that
// are impossible. Those false positives here are a consequence of how the
// shared data flow library overapproximates field flow. The library only
// tracks the head (`f`) and the length (2) of the field access path, and
// then it tracks that both `a_` and `b_` have followed `f` in _some_ access
// path somewhere in the search. That makes the library conclude that there
// could be flow to `b.f.a_` even when the flow was actually to `b.f.b_`.
sink(b.f.a()); // flow [FALSE POSITIVE through `b2.f.setB` and `b3.f.setB`]
sink(b.f.b()); // flow [FALSE POSITIVE through `b1.f.setA` and `b3.f.setA`]
}
void foo()

View File

@@ -24,7 +24,12 @@ edges
| 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 | b [post update] [c] | A.cpp:131:8:131:8 | ref arg b [c] |
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | b [post update] [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] |
@@ -36,9 +41,11 @@ edges
| 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] |
@@ -96,6 +103,34 @@ edges
| 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 |
| complex.cpp:34:15:34:15 | b [f, a_] | complex.cpp:44:8:44:8 | b [f, a_] |
| complex.cpp:34:15:34:15 | b [f, b_] | complex.cpp:45:8:45:8 | b [f, b_] |
| complex.cpp:44:8:44:8 | b [f, a_] | complex.cpp:44:10:44:10 | f [a_] |
| complex.cpp:44:10:44:10 | f [a_] | complex.cpp:44:12:44:12 | call to a |
| complex.cpp:45:8:45:8 | b [f, b_] | complex.cpp:45:10:45:10 | f [b_] |
| complex.cpp:45:10:45:10 | f [b_] | complex.cpp:45:12:45:12 | call to b |
| complex.cpp:55:3:55:4 | b1 [post update] [f, a_] | complex.cpp:61:7:61:8 | b1 [f, a_] |
| complex.cpp:55:6:55:6 | f [post update] [a_] | complex.cpp:55:3:55:4 | b1 [post update] [f, a_] |
| complex.cpp:55:13:55:22 | call to user_input | complex.cpp:55:6:55:6 | f [post update] [a_] |
| complex.cpp:56:3:56:4 | b2 [post update] [f, b_] | complex.cpp:64:7:64:8 | b2 [f, b_] |
| complex.cpp:56:6:56:6 | f [post update] [b_] | complex.cpp:56:3:56:4 | b2 [post update] [f, b_] |
| complex.cpp:56:13:56:22 | call to user_input | complex.cpp:56:6:56:6 | f [post update] [b_] |
| complex.cpp:57:3:57:4 | b3 [post update] [f, a_] | complex.cpp:67:7:67:8 | b3 [f, a_] |
| complex.cpp:57:6:57:6 | f [post update] [a_] | complex.cpp:57:3:57:4 | b3 [post update] [f, a_] |
| complex.cpp:57:13:57:22 | call to user_input | complex.cpp:57:6:57:6 | f [post update] [a_] |
| complex.cpp:58:3:58:4 | b3 [post update] [f, b_] | complex.cpp:67:7:67:8 | b3 [f, b_] |
| complex.cpp:58:6:58:6 | f [post update] [b_] | complex.cpp:58:3:58:4 | b3 [post update] [f, b_] |
| complex.cpp:58:13:58:22 | call to user_input | complex.cpp:58:6:58:6 | f [post update] [b_] |
| complex.cpp:61:7:61:8 | b1 [f, a_] | complex.cpp:34:15:34:15 | b [f, a_] |
| complex.cpp:64:7:64:8 | b2 [f, b_] | complex.cpp:34:15:34:15 | b [f, b_] |
| complex.cpp:67:7:67:8 | b3 [f, a_] | complex.cpp:34:15:34:15 | b [f, a_] |
| complex.cpp:67:7:67:8 | b3 [f, b_] | complex.cpp:34:15:34:15 | b [f, b_] |
| 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 |
@@ -145,9 +180,11 @@ edges
| 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 |
@@ -157,6 +194,11 @@ edges
| 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 |
| complex.cpp:44:12:44:12 | call to a | complex.cpp:55:13:55:22 | call to user_input | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:55:13:55:22 | call to user_input | call to user_input |
| complex.cpp:44:12:44:12 | call to a | complex.cpp:57:13:57:22 | call to user_input | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:57:13:57:22 | call to user_input | call to user_input |
| complex.cpp:45:12:45:12 | call to b | complex.cpp:56:13:56:22 | call to user_input | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:56:13:56:22 | call to user_input | call to user_input |
| complex.cpp:45:12:45:12 | call to b | complex.cpp:58:13:58:22 | call to user_input | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:58:13:58:22 | 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 |

View File

@@ -0,0 +1,16 @@
struct MyStruct
{
int x;
struct MySubStruct {
int z;
} y;
};
void test()
{
MyStruct s;
s.x = 1;
s.y.z = 1;
}

View File

@@ -0,0 +1,3 @@
| partialdefinitions.cpp:14:2:14:2 | partial def of s | partialdefinitions.cpp:14:2:14:2 | s | partialdefinitions.cpp:14:2:14:8 | ... = ... |
| partialdefinitions.cpp:15:2:15:2 | partial def of s | partialdefinitions.cpp:15:2:15:2 | s | partialdefinitions.cpp:15:2:15:10 | ... = ... |
| partialdefinitions.cpp:15:4:15:4 | partial def of y | partialdefinitions.cpp:15:4:15:4 | y | partialdefinitions.cpp:15:2:15:10 | ... = ... |

View File

@@ -0,0 +1,4 @@
import semmle.code.cpp.dataflow.internal.FlowVar
from PartialDefinition def
select def, def.getDefinedExpr(), def.getSubBasicBlockStart()

View File

@@ -133,6 +133,7 @@
| taint.cpp:165:22:165:25 | {...} | taint.cpp:172:10:172:15 | buffer | |
| taint.cpp:165:22:165:25 | {...} | taint.cpp:173:8:173:13 | buffer | |
| taint.cpp:165:24:165:24 | 0 | taint.cpp:165:22:165:25 | {...} | TAINT |
| taint.cpp:168:8:168:14 | ref arg tainted | taint.cpp:172:18:172:24 | tainted | |
| taint.cpp:170:10:170:15 | buffer | taint.cpp:170:3:170:8 | call to strcpy | |
| taint.cpp:170:10:170:15 | ref arg buffer | taint.cpp:170:3:170:8 | call to strcpy | |
| taint.cpp:170:10:170:15 | ref arg buffer | taint.cpp:171:8:171:13 | buffer | |
@@ -188,11 +189,11 @@
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field t | TAINT |
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field u | TAINT |
| taint.cpp:228:11:228:11 | `this` parameter in (constructor) | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | |
| taint.cpp:228:11:228:11 | `this` parameter in (constructor) | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | |
| taint.cpp:228:11:228:11 | constructor init of field t [post-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
| taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
| taint.cpp:228:11:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | |
| taint.cpp:228:11:232:2 | {...} | taint.cpp:228:11:232:2 | [...](...){...} | |
| taint.cpp:228:17:228:17 | `this` parameter in operator() | taint.cpp:229:3:229:6 | this | |
| taint.cpp:228:17:228:17 | `this` parameter in operator() | taint.cpp:244:3:244:6 | this | |
| taint.cpp:229:3:229:6 | this | taint.cpp:230:3:230:6 | this | |
| taint.cpp:230:3:230:6 | this | taint.cpp:231:3:231:11 | this | |
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field t | TAINT |
@@ -211,11 +212,11 @@
| taint.cpp:238:7:238:12 | call to source | taint.cpp:238:3:238:14 | ... = ... | |
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field t | TAINT |
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field u | TAINT |
| taint.cpp:243:11:243:11 | `this` parameter in (constructor) | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | |
| taint.cpp:243:11:243:11 | `this` parameter in (constructor) | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | |
| taint.cpp:243:11:243:11 | constructor init of field t [post-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
| taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
| taint.cpp:243:11:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | |
| taint.cpp:243:11:246:2 | {...} | taint.cpp:243:11:246:2 | [...](...){...} | |
| taint.cpp:243:15:243:15 | `this` parameter in operator() | taint.cpp:229:3:229:6 | this | |
| taint.cpp:243:15:243:15 | `this` parameter in operator() | taint.cpp:244:3:244:6 | this | |
| taint.cpp:244:3:244:6 | this | taint.cpp:245:3:245:6 | this | |
| taint.cpp:249:11:252:2 | [...](...){...} | taint.cpp:253:2:253:2 | d | |

View File

@@ -37,4 +37,7 @@ int Main()
// GOOD: method call with the same parameters in a different order (we only track year, month, day)
EraInfo * pDateTimeUtil4 = EraInfo::EraInfoFromDate(1, 2, 8, 1, 1989, L"\u5e73\u6210");
// BAD: constructor creating a EraInfo with exact Reiwa era start date
EraInfo * pDateTimeUtil5 = new EraInfo(2019, 5, 1);
}

View File

@@ -0,0 +1,7 @@
| ConstructorOrMethodWithExactDate.cpp:27:31:27:53 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. |
| ConstructorOrMethodWithExactDate.cpp:30:32:30:77 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. |
| ConstructorOrMethodWithExactDate.cpp:36:32:36:55 | call to EraInfoFromDate | Call that appears to have hard-coded Japanese era start date as parameter. |
| ConstructorOrMethodWithExactDate.cpp:42:32:42:54 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. |
| StructWithExactDate.cpp:31:13:31:19 | tm_year | A time struct that is initialized with exact Japanese calendar era start date. |
| StructWithExactDate.cpp:46:8:46:12 | wYear | A time struct that is initialized with exact Japanese calendar era start date. |
| StructWithExactDate.cpp:60:9:60:13 | wYear | A time struct that is initialized with exact Japanese calendar era start date. |

View File

@@ -0,0 +1 @@
Best Practices/Magic Constants/JapaneseEraDate.ql

View File

@@ -52,6 +52,13 @@ int main()
st1.wMonth = 1;
st1.wYear = 1990;
// BAD: Creation of SYSTEMTIME stuct corresponding to the beginning of Reiwa era
SYSTEMTIME st2;
st2.wDay = 1;
st2.wMonth = 5;
st2.wYear = 2019;
return 0;
}

View File

@@ -1,3 +0,0 @@
| ConstructorOrMethodWithExactDate.cpp:27:31:27:53 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. |
| ConstructorOrMethodWithExactDate.cpp:30:32:30:77 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. |
| ConstructorOrMethodWithExactDate.cpp:36:32:36:55 | call to EraInfoFromDate | Call that appears to have hard-coded Japanese era start date as parameter. |

View File

@@ -1 +0,0 @@
Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.ql

View File

@@ -1,2 +0,0 @@
| StructWithExactDate.cpp:31:13:31:19 | tm_year | A time struct that is initialized with exact Japanese calendar era start date. |
| StructWithExactDate.cpp:46:8:46:12 | wYear | A time struct that is initialized with exact Japanese calendar era start date. |

View File

@@ -1 +0,0 @@
Likely Bugs/JapaneseEra/StructWithExactEraDate.ql

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Add name mangling table
compatibility: partial

View File

@@ -75,7 +75,6 @@ private class ConstructorCall extends Call {
/** An explicit upcast. */
class ExplicitUpcast extends ExplicitCast {
ValueOrRefType src;
ValueOrRefType dest;
ExplicitUpcast() {

View File

@@ -19,7 +19,6 @@ import semmle.code.csharp.commons.ComparisonTest
/** A comparison of an index variable with the length of an array. */
class IndexGuard extends ComparisonTest {
VariableAccess indexAccess;
Variable array;
IndexGuard() {

View File

@@ -30,11 +30,8 @@ class NestedForConditions extends SC::StructuralComparisonConfiguration {
/** A nested `for` statement that shares the same iteration variable as an outer `for` statement. */
class NestedForLoopSameVariable extends ForStmt {
ForStmt outer;
Variable iteration;
MutatorOperation innerUpdate;
MutatorOperation outerUpdate;
NestedForLoopSameVariable() {

View File

@@ -6,7 +6,6 @@ import csharp
*/
class Package extends XMLElement {
string name;
Version version;
Package() {

View File

@@ -28,6 +28,7 @@ private module Cached {
forex(Throw ex | ex = m.getImplementation().getAnInstruction() | t = ex.getExpr().getType())
}
}
import Cached
pragma[noinline]

View File

@@ -204,6 +204,7 @@ module DefUse {
exists(VariableUpdate vu | def = vu.getSource() | variableUpdateUse(target, vu, use))
}
}
private import DefUse
abstract library class VariableUpdate extends Instruction {

View File

@@ -85,9 +85,7 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN
override Location getLocation() { result = Element.super.getLocation() }
override Location getALocation() {
cil_method_location(this.getSourceDeclaration(), result)
}
override Location getALocation() { cil_method_location(this.getSourceDeclaration(), result) }
override Parameter getRawParameter(int n) { cil_parameter(result, this, n, _) }

View File

@@ -40,6 +40,7 @@ private module Cached {
exists(mi.getAnInstruction())
}
}
private import Cached
predicate assemblyIsStub = assemblyIsStubImpl/1;

View File

@@ -57,9 +57,7 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type {
qualifier = this.getParent().getQualifiedName()
}
override Location getALocation() {
cil_type_location(this.getSourceDeclaration(), result)
}
override Location getALocation() { cil_type_location(this.getSourceDeclaration(), result) }
/** Holds if this type is a class. */
predicate isClass() { cil_class(this) }

View File

@@ -175,7 +175,6 @@ private newtype TAnnotatedType =
/** A type with additional information. */
class AnnotatedType extends TAnnotatedType {
Type type;
Annotations::TypeAnnotations annotations;
AnnotatedType() { this = TAnnotatedTypeNullability(type, annotations) }

View File

@@ -154,7 +154,6 @@ class AssignableWrite extends AssignableAccess {
*/
private class RefArg extends AssignableAccess {
private Expr call;
private int position;
RefArg() {
@@ -379,8 +378,10 @@ module AssignableInternal {
)
}
}
import Cached
}
private import AssignableInternal
/**
@@ -526,7 +527,6 @@ module AssignableDefinitions {
*/
class TupleAssignmentDefinition extends AssignableDefinition, TTupleAssignmentDefinition {
AssignExpr ae;
Expr leaf;
TupleAssignmentDefinition() { this = TTupleAssignmentDefinition(ae, leaf) }

View File

@@ -372,4 +372,5 @@ private module Cached {
)
}
}
import Cached

View File

@@ -949,7 +949,6 @@ class TupleType extends ValueType, @tuple_type {
*/
class TypeMention extends @type_mention {
Type type;
@type_mention_parent parent;
TypeMention() { type_mention(this, getTypeRef(type), parent) }

View File

@@ -208,7 +208,6 @@ class VSTestAssertNonNullMethod extends AssertNonNullMethod {
/** A method that forwards to another assertion method. */
class ForwarderAssertMethod extends AssertMethod {
Assertion a;
Parameter p;
ForwarderAssertMethod() {

View File

@@ -9,13 +9,9 @@ class Diagnostic extends @diagnostic {
Compilation getCompilation() { diagnostic_for(this, result, _, _) }
int severity;
string tag;
string message;
string fullMessage;
Location location;
Diagnostic() { diagnostics(this, severity, tag, message, fullMessage, location) }
@@ -67,15 +63,10 @@ class CompilerError extends Diagnostic {
/** A message from an extractor. */
class ExtractorMessage extends @extractor_message {
int severity;
string origin;
string text;
string element;
string stackTrace;
Location location;
ExtractorMessage() {

View File

@@ -338,6 +338,7 @@ private module Internal {
predicate bbIPostDominates(BasicBlock dom, BasicBlock bb) =
idominance(exitBB/1, predBB/2)(_, dom, bb)
}
private import Internal
/**

View File

@@ -282,7 +282,6 @@ module ControlFlow {
*/
class ElementNode extends Node, TElementNode {
private Splits splits;
private ControlFlowElement cfe;
ElementNode() { this = TElementNode(cfe, splits) }
@@ -1891,6 +1890,7 @@ module ControlFlow {
)
}
}
import Successor
cached
@@ -1954,6 +1954,7 @@ module ControlFlow {
cached
ControlFlowElement getAControlFlowExitNode(ControlFlowElement cfe) { result = last(cfe, _) }
}
import Cached
/** A control flow element that is split into multiple control flow nodes. */
@@ -1961,5 +1962,6 @@ module ControlFlow {
SplitControlFlowElement() { strictcount(this.getAControlFlowNode()) > 1 }
}
}
private import Internal
}

View File

@@ -194,6 +194,7 @@ module AbstractValues {
override string toString() { if this.isEmpty() then result = "empty" else result = "non-empty" }
}
}
private import AbstractValues
/**
@@ -480,9 +481,7 @@ private AssignableAccess getATrackedAccess(Ssa::Definition def, ControlFlow::Nod
*/
class GuardedExpr extends AccessOrCallExpr {
private Guard g;
private AccessOrCallExpr sub0;
private AbstractValue v0;
GuardedExpr() { isGuardedByExpr(this, g, sub0, v0) }
@@ -545,9 +544,7 @@ class GuardedExpr extends AccessOrCallExpr {
*/
class GuardedControlFlowNode extends ControlFlow::Nodes::ElementNode {
private Guard g;
private AccessOrCallExpr sub0;
private AbstractValue v0;
GuardedControlFlowNode() { g.controlsNode(this, sub0, v0) }
@@ -597,9 +594,7 @@ class GuardedControlFlowNode extends ControlFlow::Nodes::ElementNode {
*/
class GuardedDataFlowNode extends DataFlow::ExprNode {
private Guard g;
private AccessOrCallExpr sub0;
private AbstractValue v0;
GuardedDataFlowNode() {
@@ -1455,8 +1450,10 @@ module Internal {
).getARead()
}
}
import CachedWithCFG
}
import PreCFG
/**
@@ -1576,6 +1573,7 @@ module Internal {
)
}
}
import Cached
/**
@@ -1612,4 +1610,5 @@ module Internal {
)
}
}
private import Internal

View File

@@ -659,7 +659,6 @@ class BreakNormalCompletion extends NormalCompletion, TBreakNormalCompletion {
*/
class NestedCompletion extends Completion, TNestedCompletion {
private NormalCompletion inner;
private Completion outer;
NestedCompletion() { this = TNestedCompletion(inner, outer) }

View File

@@ -74,6 +74,7 @@ private module Cached {
)
}
}
private import Cached
/**
@@ -902,7 +903,6 @@ module BooleanSplitting {
*/
class BooleanSplitImpl extends SplitImpl, TBooleanSplit {
private BooleanSplitSubKind kind;
private boolean branch;
BooleanSplitImpl() { this = TBooleanSplit(kind, branch) }
@@ -1393,6 +1393,7 @@ private module SuccSplits {
case2(pred, predSplits, succ, succSplits, c)
}
}
import SuccSplits
/** Provides logic for calculating reachable control flow nodes. */

View File

@@ -66,7 +66,6 @@ class NonDelegateCallArgumentCallContext extends ArgumentCallContext, TArgNonDel
/** An argument of a delegate call. */
class DelegateCallArgumentCallContext extends ArgumentCallContext, TArgDelegateCallContext {
DelegateCall dc;
int arg;
DelegateCallArgumentCallContext() { this = TArgDelegateCallContext(dc, arg) }
@@ -93,7 +92,6 @@ class DelegateCallArgumentCallContext extends ArgumentCallContext, TArgDelegateC
class DelegateArgumentToLibraryCallableArgumentContext extends ArgumentCallContext,
TDelegateToLibraryCallableArgCallContext {
Expr delegate;
int arg;
DelegateArgumentToLibraryCallableArgumentContext() {

View File

@@ -111,6 +111,7 @@ private module Cached {
)
}
}
import Cached
/** An unbound callable. */

View File

@@ -345,11 +345,8 @@ abstract class PathNode extends TPathNode {
private class SourcePathNode extends PathNode, TSourcePathNode {
private Ssa::Definition def;
private string msg;
private Element reason;
private boolean isNullArgument;
SourcePathNode() { this = TSourcePathNode(def, msg, reason, isNullArgument) }
@@ -385,7 +382,6 @@ private class SourcePathNode extends PathNode, TSourcePathNode {
private class InternalPathNode extends PathNode, TInternalPathNode {
private Ssa::Definition def;
private BasicBlock bb;
InternalPathNode() { this = TInternalPathNode(def, bb) }
@@ -405,11 +401,8 @@ private class InternalPathNode extends PathNode, TInternalPathNode {
private class SinkPathNode extends PathNode, TSinkPathNode {
private Ssa::Definition def;
private BasicBlock bb;
private int i;
private Dereference d;
SinkPathNode() { this = TSinkPathNode(def, bb, i, d) }

View File

@@ -76,6 +76,7 @@ module Ssa {
)
}
}
import Cached
/**
@@ -359,6 +360,7 @@ module Ssa {
exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk, rk))
}
}
private import SourceVariableImpl
/**
@@ -490,6 +492,7 @@ module Ssa {
override string toString() { result = getQualifier() + "." + getAssignable() }
}
}
private import SourceVariables
private module TrackedVariablesImpl {
@@ -536,6 +539,7 @@ module Ssa {
)
}
}
private import TrackedVariablesImpl
/**
@@ -874,8 +878,10 @@ module Ssa {
)
}
}
import Cached
}
private import SsaDefReaches
/**
@@ -1339,6 +1345,7 @@ module Ssa {
)
}
}
private import FieldOrPropsImpl
/**
@@ -1538,6 +1545,7 @@ module Ssa {
)
}
}
private import CapturedVariableImpl
/**
@@ -1797,6 +1805,7 @@ module Ssa {
liveAfterWriteCapturedIn(bb, i, v, _, _, _)
}
}
private import CapturedVariableLivenessImpl
cached
@@ -1955,6 +1964,7 @@ module Ssa {
)
}
}
private import SsaImpl
private string getSplitString(Definition def) {
@@ -2289,7 +2299,6 @@ module Ssa {
*/
class ExplicitDefinition extends Definition, TSsaExplicitDef {
TrackedVar tv;
AssignableDefinition ad;
ExplicitDefinition() { this = TSsaExplicitDef(tv, ad, _, _) }

View File

@@ -227,6 +227,7 @@ private module Cached {
)
}
}
import Cached
predicate viableCallable = viableImpl/1;
@@ -321,7 +322,6 @@ abstract class DataFlowCall extends TDataFlowCall {
/** A non-delegate C# call relevant for data flow. */
class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
private ControlFlow::Nodes::ElementNode cfn;
private DispatchCall dc;
NonDelegateDataFlowCall() { this = TNonDelegateCall(cfn, dc) }
@@ -352,7 +352,6 @@ abstract class DelegateDataFlowCall extends DataFlowCall {
/** An explicit delegate call relevant for data flow. */
class ExplicitDelegateDataFlowCall extends DelegateDataFlowCall, TExplicitDelegateCall {
private ControlFlow::Nodes::ElementNode cfn;
private DelegateCall dc;
ExplicitDelegateDataFlowCall() { this = TExplicitDelegateCall(cfn, dc) }
@@ -379,7 +378,6 @@ class ExplicitDelegateDataFlowCall extends DelegateDataFlowCall, TExplicitDelega
*/
class ImplicitDelegateDataFlowCall extends DelegateDataFlowCall, TImplicitDelegateCall {
private ControlFlow::Nodes::ElementNode cfn;
private DelegateArgumentToLibraryCallable arg;
ImplicitDelegateDataFlowCall() { this = TImplicitDelegateCall(cfn, arg) }

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

View File

@@ -1655,11 +1655,8 @@ module PathGraph {
*/
private class PathNodeMid extends PathNode, TPathNodeMid {
Node node;
CallContext cc;
AccessPath ap;
Configuration config;
PathNodeMid() { this = TPathNodeMid(node, cc, ap, config) }
@@ -1722,7 +1719,6 @@ private class PathNodeSource extends PathNodeMid {
*/
private class PathNodeSink extends PathNode, TPathNodeSink {
Node node;
Configuration config;
PathNodeSink() { this = TPathNodeSink(node, config) }
@@ -2190,11 +2186,8 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2459,6 +2452,7 @@ private module FlowExploration {
)
}
}
import FlowExploration
private predicate partialFlow(

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