diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index 8242e37a8a3f..dbff2f878f97 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -596,26 +596,31 @@ fn translation_rules() -> Vec> { ), // A function parameter. With two names (`firstName`+`secondName`) the // first is the external argument label and the second the internal name; - // with one name it is just the internal name. The declared type is - // emitted; the default value is optional. + // with one name it is both the external and internal name. rule!( (functionParameter firstName: @@first - secondName: _? @@second + secondName: @@second type: @ty defaultValue: (initializerClause value: @val)?) => - parameter { - let (external, name) = match second { - Some(second) => (Some(tree!((identifier #{first}))), second), - None => (None, first), - }; - tree!((parameter - external_name_node: {external} - pattern: (identifier #{name}) - type: {ty} - default: {val})) - } + (parameter + external_name_node: (identifier #{first}) + pattern: (identifier #{second}) + type: {ty} + default: {val}) + ), + rule!( + (functionParameter + firstName: @@first + type: @ty + defaultValue: (initializerClause value: @val)?) + => + (parameter + external_name_node: (identifier #{first}) // duplicate the parameter name + pattern: (identifier #{first}) + type: {ty} + default: {val}) ), // Swift's `[T](...)` array-type constructor syntax is parsed as a call // whose callee is an `arrayExpr` containing `T`. For a generic `T`, diff --git a/unified/extractor/tests/corpus/swift/functions/function-with-default-parameter-value.output b/unified/extractor/tests/corpus/swift/functions/function-with-default-parameter-value.output index 65da7fc5c00f..e4a29f540ab9 100644 --- a/unified/extractor/tests/corpus/swift/functions/function-with-default-parameter-value.output +++ b/unified/extractor/tests/corpus/swift/functions/function-with-default-parameter-value.output @@ -68,7 +68,8 @@ top_level source="⟨body⟩" function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩" name_node: identifier "greet" source="greet" parameter: - parameter source="⟨pattern⟩: ⟨type⟩ = ⟨default⟩" + parameter source="⟨external_name_node⟩⟨pattern⟩: ⟨type⟩ = ⟨default⟩" + external_name_node: identifier "name" source="name" type: identifier "String" source="String" pattern: identifier "name" source="name" default: string_literal "\"world\"" source="\"world\"" diff --git a/unified/extractor/tests/corpus/swift/types/class-with-initializer.output b/unified/extractor/tests/corpus/swift/types/class-with-initializer.output index f5e85a979d67..19466f4989e8 100644 --- a/unified/extractor/tests/corpus/swift/types/class-with-initializer.output +++ b/unified/extractor/tests/corpus/swift/types/class-with-initializer.output @@ -100,7 +100,8 @@ top_level source="⟨body⟩" type: identifier "Int" source="Int" constructor_declaration source="⟨body⟩⟨parameter⟩" parameter: - parameter source="⟨pattern⟩: ⟨type⟩" + parameter source="⟨external_name_node⟩⟨pattern⟩: ⟨type⟩" + external_name_node: identifier "x" source="x" type: identifier "Int" source="Int" pattern: identifier "x" source="x" body: diff --git a/unified/ql/consistency-queries/DataFlowConsistency.ql b/unified/ql/consistency-queries/DataFlowConsistency.ql index 267abd674cb5..00a782f847c1 100644 --- a/unified/ql/consistency-queries/DataFlowConsistency.ql +++ b/unified/ql/consistency-queries/DataFlowConsistency.ql @@ -2,7 +2,11 @@ private import unified private import codeql.unified.internal.dataflow.AllDataFlow private import codeql.dataflow.internal.DataFlowImplConsistency -module ConsistencyInput implements InputSig { } +module ConsistencyInput implements InputSig { + predicate argHasPostUpdateExclude(DataFlowInput::ArgumentNode n) { + not exists(n.getBasicBlock()) // ignore unreachable data flow nodes + } +} module ConsistencyOutput = MakeConsistency; diff --git a/unified/ql/lib/codeql/unified/internal/AnalysisQuality.qll b/unified/ql/lib/codeql/unified/internal/AnalysisQuality.qll index d5eb5071176e..d6165688e3dc 100644 --- a/unified/ql/lib/codeql/unified/internal/AnalysisQuality.qll +++ b/unified/ql/lib/codeql/unified/internal/AnalysisQuality.qll @@ -1,6 +1,9 @@ private import unified private import codeql.util.ReportStats private import codeql.unified.internal.NameBinding +private import codeql.unified.internal.dataflow.DataFlowCall +private import codeql.unified.internal.dataflow.DataFlowCallable +private import codeql.unified.internal.dataflow.CallGraph /** Stats about name nodes that static name binding could resolve. */ module StaticNameResolutionStats implements EntityStatsSig { @@ -87,3 +90,19 @@ module FilesCoveredByModuleManifestStats implements EntityStatsSig { module FilesCoveredByModuleManifestStatsReport = EntityReportStats; + +module CallGraphStats implements EntityStatsSig { + class Candidate extends CallExpr { + DataFlowCall getDataFlowCall() { result.asExplicitCall() = this } + + DataFlowCallable getTarget() { result = viableCallable(this.getDataFlowCall()) } + + predicate isOk() { exists(this.getTarget()) } + } + + string getOkText() { result = "calls with call target" } + + string getNotOkText() { result = "calls with missing call target" } +} + +module CallGraphStatsReport = EntityReportStats; diff --git a/unified/ql/lib/codeql/unified/internal/FacadeAst.qll b/unified/ql/lib/codeql/unified/internal/FacadeAst.qll index 67473ac728b5..31b3ec3d950d 100644 --- a/unified/ql/lib/codeql/unified/internal/FacadeAst.qll +++ b/unified/ql/lib/codeql/unified/internal/FacadeAst.qll @@ -117,6 +117,19 @@ module Unified { class Argument extends G::Argument { /** Gets the name of this argument. */ string getName() { result = this.getNameNode().getValue() } + + /** Holds if this is a positional argument. */ + predicate isPositional() { not exists(this.getName()) } + + /** Gets the 0-based index of this argument among the positional arguments in the surrounding call or tuple. */ + int getPositionalIndex() { + this = + rank[result + 1](Argument a | + a.getParent() = this.getParent() and a.isPositional() + | + a order by a.getParentIndex() + ) + } } class AssociatedTypeDeclaration extends G::AssociatedTypeDeclaration { @@ -172,8 +185,28 @@ module Unified { } class Parameter extends G::Parameter { - /** Gets the external name of this parameter. */ - string getExternalName() { result = this.getExternalNameNode().getValue() } + /** + * Gets the external name of this parameter. + * + * Has no result for pseudo-names like `_` that indicate that this is actually a positional parameter. + */ + string getExternalName() { result = this.getExternalNameNode().getValue() and not result = "_" } + + /** Gets the callable on which this parameter appears. */ + Callable getDeclaringCallable() { result = this.getParent() } + + /** Holds if this is a positional parameter. */ + predicate isPositional() { not exists(this.getExternalName()) } + + /** Gets the 0-based index of this parameter among the positional parameters of the declaring callable. */ + int getPositionalIndex() { + this = + rank[result + 1](Parameter p | + p.getDeclaringCallable() = this.getDeclaringCallable() and p.isPositional() + | + p order by p.getParentIndex() + ) + } } class TypeAliasDeclaration extends G::TypeAliasDeclaration { diff --git a/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll b/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll index 0844fe64bed9..716e3e7182a1 100644 --- a/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll +++ b/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll @@ -474,3 +474,11 @@ class PotentialLocalNameAccess extends IdentifierExpr { /** Holds if this is one of the binding sites for a name, such as the `x` in `let x = 123`. */ predicate isBindingSite() { this instanceof NameBinding } } + +/** Gets implicitly-declared variable through which the given callable refers to its receiver. */ +LocalVariable getImplicitReceiverVariable(Callable callable) { + exists(string name | + name = any(NameBindingPlugin p).getImplicitReceiverParameterName(callable) and + result.(LocalNameBindingOutput::ImplicitLocal).hasNameAndScope(name, callable) + ) +} diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll b/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll index 893e62d3b140..0d44eea6cb1e 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll @@ -1,11 +1,15 @@ /** Re-exports all the files in the internal dataflow folder (except DataFlowPublic). */ +import CallGraph import Content +import DataFlowCall +import DataFlowCallable import DataFlowGraph import DataFlowInstantiation import DataFlowNode import DataFlowPlugin -import Step import LocalSsa +import ParameterPositions +import Step import TaintTrackingInstantiation import VariableRefKind diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/CallGraph.qll b/unified/ql/lib/codeql/unified/internal/dataflow/CallGraph.qll new file mode 100644 index 000000000000..226e2f15d93b --- /dev/null +++ b/unified/ql/lib/codeql/unified/internal/dataflow/CallGraph.qll @@ -0,0 +1,16 @@ +private import unified +private import AllDataFlow +private import codeql.unified.internal.NameBinding as N + +private Callable getCallableFromNameBinding(NameBinding binding) { + binding = result.(FunctionDeclaration).getNameNode() +} + +DataFlowCallable viableCallable(DataFlowCall c) { + exists(CallExpr call, Callable callable, NameBinding target | + c.asExplicitCall() = call and + target = N::getStaticBindingTarget(N::getIdentifierFromRef(call.getCallee())) and + callable = getCallableFromNameBinding(target) and + result.asSourceCallable() = callable + ) +} diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCall.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCall.qll new file mode 100644 index 000000000000..462515880cf3 --- /dev/null +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCall.qll @@ -0,0 +1,30 @@ +private import unified +private import AllDataFlow +private import codeql.unified.internal.ExprPositions + +private newtype TDataFlowCall = + TExplicitCall(CallExpr call) { + not isInBindingContext(call, _) // ignore constructor patterns + } + +/** + * A call site, covering both explicit calls such as `foo(1,2)`, as well an implicit + * calls and calls derived from library models. + * + * Currently only explicit calls are implemented. + */ +class DataFlowCall extends TDataFlowCall { + /** Gets the `CallExpr` wrapped by this dataflow call, if any. */ + CallExpr asExplicitCall() { this = TExplicitCall(result) } + + /** Gets a string representation of this call. */ + string toString() { result = this.asExplicitCall().toString() } + + /** Gets the location of this call, if any. */ + Location getLocation() { result = this.asExplicitCall().getLocation() } + + /** Gets the callable containing this call. */ + DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.asExplicitCall().getEnclosingCallable() + } +} diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll new file mode 100644 index 000000000000..40f6934ebae7 --- /dev/null +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll @@ -0,0 +1,21 @@ +private import unified +private import AllDataFlow + +private newtype TDataFlowCallable = TSourceCallable(Callable callable) + +/** + * A callable entity, either an function-like entity in the source code, + * an entity derived from a library model. + * + * Currently only callables in source code are implemented. + */ +class DataFlowCallable extends TDataFlowCallable { + /** Gets the `Callable` wrapped by this dataflow callable, if any. */ + Callable asSourceCallable() { this = TSourceCallable(result) } + + /** Gets a string representation of this call. */ + string toString() { result = this.asSourceCallable().toString() } + + /** Gets the location of this call, if any. */ + Location getLocation() { result = this.asSourceCallable().getLocation() } +} diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll index 2bd96b2b3ef1..4ba0fdcb802c 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll @@ -1,9 +1,38 @@ private import unified private import AllDataFlow +private import codeql.unified.internal.LocalNameBinding predicate step(Node node1, Step step, Node node2) { any(DataFlowPlugin p).step(node1, step, node2) or + exists(Callable callable | + node1.isReceiverParameter(callable) and + step.value() and + node2.isLocalVariableWrite(callable, getImplicitReceiverVariable(callable)) + ) + or + exists(CallExpr call, Expr receiverExpr | + receiverExpr = call.getCallee().(MemberAccessExpr).getBase() + | + node1.isResultValue(receiverExpr) and + step.value() and + node2.isReceiverArgument(call) + or + node1.isReceiverPostUpdate(call) and + step.value() and + node2.isPostUpdate(receiverExpr) + ) + or + exists(CallExpr call, UnqualifiedMemberAccess callee | callee = call.getCallee() | + node1.isLocalVariableRead(callee, callee.getImplicitQualifierVariable()) and + step.value() and + node2.isReceiverArgument(call) + or + node1.isReceiverPostUpdate(call) and + step.value() and + node2.isLocalVariablePostUpdate(callee, callee.getImplicitQualifierVariable()) + ) + or exists(VariableDeclaration decl | node1.isResultValue(decl.getValue()) and step.value() and diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll index da5602cddd29..e104a351a172 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll @@ -22,66 +22,77 @@ module DataFlowInput implements InputSig { // // Parameter, argument, return, and out nodes and their positions/kinds // - class ParameterNode extends Node { - ParameterNode() { none() } // TODO - } - - class ArgumentNode extends Node { - ArgumentNode() { none() } // TODO - } - class ReturnNode extends Node { - ReturnNode() { none() } // TODO + ReturnNode() { this.asExpr() = any(ReturnExpr r).getValue() } - ReturnKind getKind() { none() } // TODO + ReturnKind getKind() { exists(result) } } class OutNode extends Node { - OutNode() { none() } // TODO + OutNode() { this.asExpr() instanceof CallExpr } } class ReturnKind = Unit; - class ParameterPosition extends Void { - ParameterPosition() { none() } // TODO - - bindingset[this] - string toString() { none() } // TODO - } - - class ArgumentPosition extends Void { - ArgumentPosition() { none() } // TODO - - bindingset[this] - string toString() { none() } // TODO - } - - predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { none() } // TODO - + import ParameterPositions // // Calls and callables // - class DataFlowCall extends Void { - Location getLocation() { none() } // TODO - - DataFlowCallable getEnclosingCallable() { none() } // TODO + import DataFlowCall + import DataFlowCallable + import CallGraph + + DataFlowCallable nodeGetEnclosingCallable(Node node) { result = node.getEnclosingCallableEx() } + + private predicate isParameterNodeImpl(Node p, DataFlowCallable c, ParameterPosition pos) { + exists(Parameter param | + p.asExpr() = param.getPattern() and + c.asSourceCallable() = param.getEnclosingCallable() + | + pos.asPositional() = param.getPositionalIndex() + or + pos.asNamed() = param.getExternalName() + ) + or + p.isReceiverParameterEx(c) and + pos.isReceiver() } - class DataFlowCallable = Callable; // TODO: Use newtype - - DataFlowCallable viableCallable(DataFlowCall c) { none() } // TODO - - DataFlowCallable nodeGetEnclosingCallable(Node node) { result = node.getEnclosingCallable() } + class ParameterNode extends Node { + ParameterNode() { isParameterNodeImpl(this, _, _) } + } predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) { - none() // TODO + // This predicate is needed to implement the signature without empty recursion through ParameterNode + isParameterNodeImpl(p, c, pos) + } + + private predicate isArgumentNodeImpl(Node n, DataFlowCall call, ArgumentPosition pos) { + exists(Argument arg | + n.asExpr() = arg.getValue() and + call.asExplicitCall().getAnArgument() = arg + | + pos.asPositional() = arg.getPositionalIndex() + or + pos.asNamed() = arg.getName() + ) + or + n.isReceiverArgumentEx(call) and + pos.isReceiver() + } + + class ArgumentNode extends Node { + ArgumentNode() { isArgumentNodeImpl(this, _, _) } } predicate isArgumentNode(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) { - none() // TODO + // This predicate is needed to implement the signature without empty recursion through ArgumentNode + isArgumentNodeImpl(n, call, pos) } - OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { none() } // TODO + OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { + result.asExpr() = call.asExplicitCall() and exists(kind) + } // // Post-update nodes diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll index 09cf4b9f4606..6defd397c0be 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll @@ -1,11 +1,24 @@ private import unified private import AllDataFlow private import codeql.unified.internal.ExprPositions +private import codeql.unified.internal.LocalNameBinding +private import codeql.util.Boolean private predicate hasIncomingValueAtCfgNode(Expr expr, ControlFlowNode cfgNode) { - exists(AstNode declOrAssignment | - hasIncomingValue(expr, declOrAssignment) and - cfgNode.injects(declOrAssignment) + exists(AstNode declOrAssignment | hasIncomingValue(expr, declOrAssignment) | + // In cases where the CFG node for 'expr' appears before its actual assignment, + // use the CFG node from the surrounding assignment-like node + cfgNode.injects(declOrAssignment.(Assignment)) + or + // Variable declarations are pre-order and visit the target first. + // Use the after node. + cfgNode.isAfter(declOrAssignment.(VariableDeclaration)) + or + // In other cases, it's a binding pattern whose CFG node can be used + // as its assignment time + not declOrAssignment instanceof Assignment and + not declOrAssignment instanceof VariableDeclaration and + cfgNode.injects(expr) ) } @@ -14,16 +27,24 @@ private predicate hasPostUpdate(Expr expr, ControlFlowNode cfgNode) { (hasIncomingValueAtCfgNode(member, cfgNode) or hasPostUpdate(member, cfgNode)) and expr = member.getBase() ) + or + exists(CallExpr call | cfgNode.isAfter(call) | + expr = call.getAnArgument().getValue() + or + expr = call.getCallee().(MemberAccessExpr).getBase() + ) } /** - * Holds if `expr` performs an access to `var` of the given `kind` at `cfgNode`. + * Holds if `repr` performs an access to `var` of the given `kind` at `cfgNode`. + * + * `repr` should be an arbitary but unique representative for the access. */ predicate performsVariableAccess( - Expr expr, LocalVariable var, VariableRefKind kind, ControlFlowNode cfgNode + AstNode repr, LocalVariable var, VariableRefKind kind, ControlFlowNode cfgNode ) { - exists(LocalVariableAccess access | var = access.getLocalVariable() and expr = access | - hasResultValue(access) and kind.isRead() and cfgNode.asExpr() = expr + exists(LocalVariableAccess access | var = access.getLocalVariable() and repr = access | + hasResultValue(access) and kind.isRead() and cfgNode.asExpr() = repr or hasIncomingValueAtCfgNode(access, cfgNode) and kind.isWrite() or @@ -31,12 +52,25 @@ predicate performsVariableAccess( ) or exists(UnqualifiedMemberAccess access | - access.isInstanceAccess() and var = access.getImplicitQualifierVariable() and expr = access + access.isInstanceAccess() and var = access.getImplicitQualifierVariable() and repr = access | kind.isRead() and cfgNode.isBefore(access) or (hasIncomingValueAtCfgNode(access, cfgNode) or hasPostUpdate(access, cfgNode)) and kind.isPostUpdate() + or + exists(CallExpr call | + access = call.getCallee() and + cfgNode.isAfter(call) and + kind.isPostUpdate() + ) + ) + or + exists(Callable callable | + repr = callable and + var = getImplicitReceiverVariable(callable) and + kind.isWrite() and + cfgNode.(ControlFlow::EntryNode).getEnclosingCallable() = callable ) } @@ -44,10 +78,12 @@ newtype TDataFlowNode = TValueNode(Expr expr) { hasResultValue(expr) or hasIncomingValue(expr, _) } or TStrictlyIncomingValue(Expr expr) { hasResultValue(expr) and hasIncomingValue(expr, _) } or TExprPostUpdateNode(Expr expr) { hasPostUpdate(expr, _) } or - TLocalVariableRefNode(Expr expr, LocalVariable var, VariableRefKind kind) { - performsVariableAccess(expr, var, kind, _) + TLocalVariableRefNode(AstNode repr, LocalVariable var, VariableRefKind kind) { + performsVariableAccess(repr, var, kind, _) } or - TLocalSsaNode(LocalSsaDataFlowOutput::SsaNode node) + TLocalSsaNode(LocalSsaDataFlowOutput::SsaNode node) or + TReceiverParameterNode(DataFlowCallable callable) or + TReceiverArgumentNode(DataFlowCall call, Boolean isPost) /** * A node representing something that can have a value. @@ -68,29 +104,70 @@ class Node extends TDataFlowNode { this = TStrictlyIncomingValue(expr) } - /** Holds if this represents the reference to `v` at `access`. */ - predicate isLocalVariableRef(Expr access, LocalVariable v, VariableRefKind kind) { - this = TLocalVariableRefNode(access, v, kind) + /** Holds if this represents the reference to `v` at `repr`. */ + predicate isLocalVariableRef(AstNode repr, LocalVariable v, VariableRefKind kind) { + this = TLocalVariableRefNode(repr, v, kind) } - /** Holds if this represents the value read from `v` at `access`. */ - predicate isLocalVariableRead(Expr access, LocalVariable v) { - this.isLocalVariableRef(access, v, TRead()) + /** Holds if this represents the value read from `v` at `repr`. */ + predicate isLocalVariableRead(AstNode repr, LocalVariable v) { + this.isLocalVariableRef(repr, v, TRead()) } - /** Holds if this represents the value written to `v` at `access`. */ - predicate isLocalVariableWrite(Expr access, LocalVariable v) { - this.isLocalVariableRef(access, v, TWrite()) + /** Holds if this represents the value written to `v` at `repr`. */ + predicate isLocalVariableWrite(AstNode repr, LocalVariable v) { + this.isLocalVariableRef(repr, v, TWrite()) } /** Holds if this represents the updated state of the value held in `v` after it has been mutated by the surrounding assignment or call. */ - predicate isLocalVariablePostUpdate(Expr access, LocalVariable v) { - this.isLocalVariableRef(access, v, TPostUpdate()) + predicate isLocalVariablePostUpdate(AstNode repr, LocalVariable v) { + this.isLocalVariableRef(repr, v, TPostUpdate()) } /** Holds if this represents the updated state of the value returned by `expr` after it has been mutated by the surrounding assignment or call. */ predicate isPostUpdate(Expr expr) { this = TExprPostUpdateNode(expr) } + /** + * Holds if this represents the receiver passed to the given callable. + * + * Note that for non-methods and closures that capture the receiver from the enclosing method, + * this node still exists but will typically not flow anywhere. + */ + predicate isReceiverParameter(Callable callable) { + this.isReceiverParameterEx(any(DataFlowCallable c | c.asSourceCallable() = callable)) + } + + /** + * Holds if this represents the receiver passed to the given callable. + * + * Note that for non-methods and closures that capture the receiver from the enclosing method, + * this node still exists but will typically not flow anywhere. + */ + predicate isReceiverParameterEx(DataFlowCallable callable) { + this = TReceiverParameterNode(callable) + } + + /** Holds if this node represents the receiver argument passed to `call`. */ + predicate isReceiverArgument(CallExpr call) { + this.isReceiverArgumentEx(any(DataFlowCall c | c.asExplicitCall() = call)) + } + + /** Holds if this node represents the updated state of the receiver of `call` after the call returns. */ + predicate isReceiverPostUpdate(CallExpr call) { + this.isReceiverPostUpdateEx(any(DataFlowCall c | c.asExplicitCall() = call)) + } + + /** Holds if this node represents the receiver argument passed to `call`. */ + predicate isReceiverArgumentEx(DataFlowCall call) { this.isReceiverArgumentEx(call, false) } + + /** Holds if this node represents the updated state of the receiver of `call` after the call returns. */ + predicate isReceiverPostUpdateEx(DataFlowCall call) { this.isReceiverArgumentEx(call, true) } + + /** Holds if this node represents the receiver argument passed to `call`. */ + predicate isReceiverArgumentEx(DataFlowCall call, boolean isPost) { + this = TReceiverArgumentNode(call, isPost) + } + /** Gets the expression represented by this node. */ Expr asExpr() { this = TValueNode(result) } @@ -100,8 +177,7 @@ class Node extends TDataFlowNode { AstNode getWrappedAstNode() { result = this.asExpr() or this = TStrictlyIncomingValue(result) or - this = TExprPostUpdateNode(result) or - this = TLocalVariableRefNode(result, _, _) + this = TExprPostUpdateNode(result) } /** Get a string representation of this element. */ @@ -125,27 +201,120 @@ class Node extends TDataFlowNode { this = TLocalSsaNode(node) and result = node.toString() ) + or + exists(DataFlowCallable callable | + this.isReceiverParameterEx(callable) and + result = "[receiver] " + callable.toString() + ) + or + exists(DataFlowCall call | + this.isReceiverArgumentEx(call) and + result = "[receiver arg] " + call.toString() + or + this.isReceiverPostUpdateEx(call) and + result = "[receiver post] " + call.toString() + ) } /** Gets the location of this data flow node. */ Location getLocation() { result = this.getWrappedAstNode().getLocation() or + exists(AstNode repr | + this.isLocalVariableRef(repr, _, _) and + result = repr.getLocation() + ) + or exists(LocalSsaDataFlowOutput::SsaNode node | this = TLocalSsaNode(node) and result = node.getLocation() ) + or + exists(DataFlowCallable callable | + this.isReceiverParameterEx(callable) and + result = callable.getLocation() + ) + or + exists(DataFlowCall call | + this.isReceiverArgumentEx(call, _) and + result = call.getLocation() + ) + } + + /** Gets the data-flow callable containing this data flow node. */ + DataFlowCallable getEnclosingCallableEx() { + result.asSourceCallable() = this.getWrappedAstNode().getEnclosingCallable() + or + exists(AstNode repr, LocalVariable var, VariableRefKind kind, ControlFlowNode cfgNode | + this.isLocalVariableRef(repr, var, kind) and + performsVariableAccess(repr, var, kind, cfgNode) and + result.asSourceCallable() = cfgNode.getEnclosingCallable() + ) + or + exists(LocalSsaDataFlowOutput::SsaNode node | + this = TLocalSsaNode(node) and + result.asSourceCallable() = node.getSourceVariable().getDeclaringCallable() + ) + or + this.isReceiverParameterEx(result) + or + exists(DataFlowCall call | + this.isReceiverArgumentEx(call, _) and + result = call.getEnclosingCallable() + ) } /** Gets the callable containing this data flow node. */ - Callable getEnclosingCallable() { - result = this.getWrappedAstNode().getEnclosingCallable() + Callable getEnclosingCallable() { result = this.getEnclosingCallableEx().asSourceCallable() } + + /** + * Holds if this data flow node is associated with the `i`'th index in the given basic block. + * + * Note that some data flow nodes may have an index appearing before the first or after the + * last `ControlFlowNode` node in the basic block. Multiple data flow nodes may share the same control flow position. + * + * Also note that some data flow nodes have no associated control flow position, either because they are + * in unreachable code, or belong to a synthesized callable that has no control flow graph. + */ + predicate hasControlFlowPosition(BasicBlock bb, int i) { + exists(ControlFlowNode cfgNode | cfgNode = bb.getNode(i) | + exists(Expr expr | + this.isResultValue(expr) and cfgNode.asExpr() = expr + or + this.isIncomingValue(expr) and hasIncomingValueAtCfgNode(expr, cfgNode) + or + this.isPostUpdate(expr) and hasPostUpdate(expr, cfgNode) + ) + or + exists(AstNode repr, LocalVariable var, VariableRefKind kind | + this.isLocalVariableRef(repr, var, kind) and + performsVariableAccess(repr, var, kind, cfgNode) + ) + or + exists(DataFlowCallable callable | + this.isReceiverParameterEx(callable) and + cfgNode.(ControlFlow::EntryNode).getEnclosingCallable() = callable.asSourceCallable() + ) + or + exists(DataFlowCall call, CallExpr sourceCall | + call.asExplicitCall() = sourceCall and + ( + this.isReceiverArgumentEx(call) and cfgNode.injects(sourceCall) + or + this.isReceiverPostUpdateEx(call) and cfgNode.isAfter(sourceCall) + ) + ) + ) or exists(LocalSsaDataFlowOutput::SsaNode node | this = TLocalSsaNode(node) and - result = node.getSourceVariable().getDeclaringCallable() + bb = node.getBasicBlock() and + i = node.getIndex() // TODO: why is this marked as internal in the SSA library? ) } + + /** Gets the basic block associated with this data flow node, if any. */ + BasicBlock getBasicBlock() { this.hasControlFlowPosition(result, _) } } Node getPostUpdateNode(Node pre) { @@ -158,4 +327,9 @@ Node getPostUpdateNode(Node pre) { pre.isLocalVariableRead(expr, var) and result.isLocalVariablePostUpdate(expr, var) ) + or + exists(DataFlowCall call | + pre.isReceiverArgumentEx(call) and + result.isReceiverPostUpdateEx(call) + ) } diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll b/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll index 96c90fbb47ed..c69e5c799670 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll @@ -39,12 +39,17 @@ private import LocalSsaOutput module LocalSsaDataFlowInput implements DataFlowIntegrationInputSig { class Expr extends TLocalVariableRefNode { + U::AstNode repr; + LocalVariable var; + VariableRefKind kind; + + Expr() { this = TLocalVariableRefNode(repr, var, kind) } + predicate hasCfgNode(BasicBlock bb, int i) { - exists(U::Expr expr, LocalVariable var, VariableRefKind kind | - this = TLocalVariableRefNode(expr, var, kind) and - kind.isRead() and - performsVariableAccess(expr, var, kind, bb.getNode(i)) - ) + this = TLocalVariableRefNode(repr, var, kind) and + // Note: the synthetic read we insert for post-updates must also have an Expr + (kind.isRead() or kind.isPostUpdate()) and + performsVariableAccess(repr, var, kind, bb.getNode(i)) } string toString() { result = this.(Node).toString() } @@ -63,9 +68,9 @@ module LocalSsaDataFlowInput implements DataFlowIntegrationInputSig { predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, GuardValue val) { none() } predicate postUpdateCfgNode(Expr read, BasicBlock bb, int i) { - exists(LocalVariable var, U::Expr expr | - read = TLocalVariableRefNode(expr, var, TRead()) and - performsVariableAccess(expr, var, TPostUpdate(), bb.getNode(i)) + exists(LocalVariable var, U::AstNode repr | + read = TLocalVariableRefNode(repr, var, TRead()) and + performsVariableAccess(repr, var, TPostUpdate(), bb.getNode(i)) ) } } @@ -74,23 +79,54 @@ module LocalSsaDataFlowOutput = DataFlowIntegration; private module Ssa = LocalSsaDataFlowOutput; +/** + * Holds if `node` represents the synthetic read we use to represent a post-update node. + * + * We want to skip use-use flow through such a node, as we don't want use-use ordinary flow + * targeting a post-update node. + */ +private predicate postUpdateReadNode(Ssa::Node node) { + node.(Ssa::ExprNode).getExpr() = TLocalVariableRefNode(_, _, TPostUpdate()) +} + Node getNodeFromLocalSsaNode(Ssa::Node n) { result = TLocalSsaNode(n) or - result = n.(Ssa::ExprNode).getExpr() + result = n.(Ssa::ExprNode).getExpr() and + not postUpdateReadNode(n) or result = getPostUpdateNode(n.(Ssa::ExprPostUpdateNode).getExpr()) or - exists(LocalVariable v, BasicBlock bb, int i, Expr expr | + exists(LocalVariable v, BasicBlock bb, int i, AstNode repr | n.(Ssa::WriteDefSourceNode).getDefinition().definesAt(v, bb, i) and - performsVariableAccess(expr, v, TWrite(), bb.getNode(i)) and - result.isLocalVariableWrite(expr, v) + performsVariableAccess(repr, v, TWrite(), bb.getNode(i)) and + result.isLocalVariableWrite(repr, v) + ) +} + +/** + * Holds if there is use-use flow from `node1`, through one or most post-update reads, into `node2`. + */ +predicate skipPostUpdateRead(Ssa::Node node1, Ssa::Node node2) { + Ssa::localFlowStep(_, node1, node2, true) and + postUpdateReadNode(node2) + or + exists(Ssa::Node mid | + skipPostUpdateRead(node1, mid) and + postUpdateReadNode(mid) and + Ssa::localFlowStep(_, mid, node2, _) ) } predicate localSsaStep(Node node1, Node node2, boolean isUseStep) { exists(Ssa::Node ssa1, Ssa::Node ssa2 | - Ssa::localFlowStep(_, ssa1, ssa2, isUseStep) and + ( + Ssa::localFlowStep(_, ssa1, ssa2, isUseStep) + or + skipPostUpdateRead(ssa1, ssa2) and + isUseStep = true + ) and + not postUpdateReadNode(ssa2) and node1 = getNodeFromLocalSsaNode(ssa1) and node2 = getNodeFromLocalSsaNode(ssa2) ) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll b/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll new file mode 100644 index 000000000000..81a11f3a0419 --- /dev/null +++ b/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll @@ -0,0 +1,30 @@ +private import unified + +private newtype TParameterPosition = + TReceiverParameter() or + TPositionalParameter(int n) { n = [0 .. 20] } or + TNamedParameter(string name) { + name = any(Parameter p).getExternalName() + or + name = any(Argument arg).getName() + } + +class ParameterPosition extends TParameterPosition { + predicate isReceiver() { this = TReceiverParameter() } + + int asPositional() { this = TPositionalParameter(result) } + + string asNamed() { this = TNamedParameter(result) } + + string toString() { + this.isReceiver() and result = "receiver" + or + result = this.asPositional().toString() + or + result = "\"" + this.asNamed() + "\"" + } +} + +class ArgumentPosition = ParameterPosition; + +predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { apos = ppos } diff --git a/unified/ql/src/diagnostic/CallGraph.ql b/unified/ql/src/diagnostic/CallGraph.ql new file mode 100644 index 000000000000..96477bffe193 --- /dev/null +++ b/unified/ql/src/diagnostic/CallGraph.ql @@ -0,0 +1,17 @@ +/** + * @name Call graph + * @description Calls that could be resolved to a target callable + * @kind problem + * @problem.severity recommendation + * @id unified/diagnostic/call-graph + * @tags meta + * @precision very-low + */ + +import unified +import codeql.unified.internal.dataflow.DataFlowCallable +import codeql.unified.internal.AnalysisQuality + +from CallGraphStats::Candidate c, DataFlowCallable target +where target = c.getTarget() +select c, "Call to $@.", target, target.toString() diff --git a/unified/ql/src/diagnostic/ExtractorInformation.ql b/unified/ql/src/diagnostic/ExtractorInformation.ql index 6e52b4fa0887..3fc0634b3344 100644 --- a/unified/ql/src/diagnostic/ExtractorInformation.ql +++ b/unified/ql/src/diagnostic/ExtractorInformation.ql @@ -41,7 +41,8 @@ where numberOfLinesOfCode(key, value) or numberOfLinesOfCodeByExtension(key, value) or StaticNameResolutionStatsReport::keyValuePair(key, value) or - FilesCoveredByModuleManifestStatsReport::keyValuePair(key, value) + FilesCoveredByModuleManifestStatsReport::keyValuePair(key, value) or + CallGraphStatsReport::keyValuePair(key, value) ) and /* Infinity */ value != 1.0 / 0.0 and diff --git a/unified/ql/test/library-tests/BasicTest/test.expected b/unified/ql/test/library-tests/BasicTest/test.expected index 5f8e2a323ad2..0b5b75967b3b 100644 --- a/unified/ql/test/library-tests/BasicTest/test.expected +++ b/unified/ql/test/library-tests/BasicTest/test.expected @@ -141,6 +141,7 @@ identifier | test.swift:85:27:85:29 | Array | Array | | test.swift:85:28:85:28 | T | T | | test.swift:85:32:85:40 | transform | transform | +| test.swift:85:32:85:40 | transform | transform | | test.swift:85:44:85:44 | T | T | | test.swift:85:47:85:47 | T | T | | test.swift:85:53:85:53 | T | T | diff --git a/unified/ql/test/library-tests/dataflow/calls.swift b/unified/ql/test/library-tests/dataflow/calls.swift new file mode 100644 index 000000000000..9f2fedf4d3c8 --- /dev/null +++ b/unified/ql/test/library-tests/dataflow/calls.swift @@ -0,0 +1,126 @@ +func source(_ s: String) -> String { return s } + +@discardableResult +func sink(_ s: String) -> String { return "" } + +func t1() { + func target(_ x: String) { + sink(x) // $ hasValueFlow=t1.1 + } + target(source("t1.1")) +} + +func t2() { + func target() -> String { + return source("t2.1") + } + sink(target()) // $ hasValueFlow=t2.1 +} + +func t3() { + func target(x: String) { + sink(x) // $ hasValueFlow=t3.1 + } + target(x: source("t3.1")) +} + +func t4() { + func target(_ x: String) -> String { + return x + "foo" + } + sink(target(source("t4.1"))) // $ hasTaintFlow=t4.1 + sink(target(source("t4.2"))) // $ hasTaintFlow=t4.2 + sink(target("safe")) +} + +func t5() { + func target1(name x: String) { + sink(x) // $ hasValueFlow=t5.1 + } + target1(name: source("t5.1")) + + func target2(name: String) { + sink(name) // $ hasValueFlow=t5.2 + } + target2(name: source("t5.2")) +} + +func t6() { + func target(_ x: String, _ y: String) { + sink(x) // $ hasValueFlow=t6.1 + sink(y) // $ hasValueFlow=t6.2 + } + target(source("t6.1"), source("t6.2")) +} + +class Box { + var field: String = "" +} + +func t7() { + func target(_ x: Box) { + x.field = source("t7.1") + } + let b = Box() + sink(b.field) // no flow + target(b) + sink(b.field) // $ hasValueFlow=t7.1 +} + +func t8() { + class C { + var field: String = "" + + func store() { + field = source("t8.1") + } + + func read1() { + sink(field) // no flow + store() + sink(field) // $ hasValueFlow=t8.1 + } + + func read2() { + sink(field) // no flow + store() + sink(self.field) // $ hasValueFlow=t8.1 + } + + func read3() { + sink(field) // no flow + self.store() + sink(field) // $ MISSING: hasValueFlow=t8.1 // self.store() not yet resolved by call graph + } + + func read4() { + sink(field) // no flow + self.store() + sink(self.field) // $ MISSING: hasValueFlow=t8.1 // self.store() not yet resolved by call graph + } + + func read5() { + sink(self.field) // no flow + store() + sink(field) // $ hasValueFlow=t8.1 + } + + func read6() { + sink(self.field) // no flow + store() + sink(self.field) // $ hasValueFlow=t8.1 + } + + func read7() { + sink(self.field) // no flow + self.store() + sink(field) // $ MISSING: hasValueFlow=t8.1 // self.store() not yet resolved by call graph + } + + func read8() { + sink(self.field) // no flow + self.store() + sink(self.field) // $ MISSING: hasValueFlow=t8.1 // self.store() not yet resolved by call graph + } + } +} diff --git a/unified/ql/test/library-tests/dataflow/implicit-self.swift b/unified/ql/test/library-tests/dataflow/implicit-self.swift index 32f8e88266f4..87d9dc172524 100644 --- a/unified/ql/test/library-tests/dataflow/implicit-self.swift +++ b/unified/ql/test/library-tests/dataflow/implicit-self.swift @@ -1,3 +1,8 @@ +func source(_ s: String) -> String { return s } + +@discardableResult +func sink(_ s: String) -> String { return "" } + class Box { var x: String = "" } @@ -7,78 +12,78 @@ class C { var box = Box() func t1() { - sink(self.x); // no flow - self.x = source("t1.1"); - sink(self.x); // $ hasValueFlow=t1.1 + sink(self.x) // no flow + self.x = source("t1.1") + sink(self.x) // $ hasValueFlow=t1.1 } func t2() { - sink(x); // no flow - x = source("t2.1"); - sink(x); // $ hasValueFlow=t2.1 + sink(x) // no flow + x = source("t2.1") + sink(x) // $ hasValueFlow=t2.1 } func t3() { - sink(self.x); // no flow - x = source("t3.1"); - sink(self.x); // $ hasValueFlow=t3.1 + sink(self.x) // no flow + x = source("t3.1") + sink(self.x) // $ hasValueFlow=t3.1 } func t4() { - sink(x); // no flow - self.x = source("t4.1"); - sink(x); // $ hasValueFlow=t4.1 + sink(x) // no flow + self.x = source("t4.1") + sink(x) // $ hasValueFlow=t4.1 } func t5() { - sink(self.box.x); // no flow - self.box.x = source("t5.1"); - sink(self.box.x); // $ hasValueFlow=t5.1 + sink(self.box.x) // no flow + self.box.x = source("t5.1") + sink(self.box.x) // $ hasValueFlow=t5.1 } func t6() { - sink(box.x); // no flow - box.x = source("t6.1"); - sink(box.x); // $ hasValueFlow=t6.1 + sink(box.x) // no flow + box.x = source("t6.1") + sink(box.x) // $ hasValueFlow=t6.1 } func t7() { - sink(self.box.x); // no flow - box.x = source("t7.1"); - sink(self.box.x); // $ hasValueFlow=t7.1 + sink(self.box.x) // no flow + box.x = source("t7.1") + sink(self.box.x) // $ hasValueFlow=t7.1 } func t8() { - sink(box.x); // no flow - self.box.x = source("t8.1"); - sink(box.x); // $ hasValueFlow=t8.1 + sink(box.x) // no flow + self.box.x = source("t8.1") + sink(box.x) // $ hasValueFlow=t8.1 } func t9() { - x = "safe"; - x += sink(x) + source("t9.1"); - sink(x); // $ hasTaintFlow=t9.1 - sink(self.x); // $ hasTaintFlow=t9.1 + x = "safe" + x += sink(x) + source("t9.1") + sink(x) // $ hasTaintFlow=t9.1 + sink(self.x) // $ hasTaintFlow=t9.1 } func t10() { - x = "safe"; - self.x += sink(x) + source("t10.1"); - sink(x); // $ hasTaintFlow=t10.1 - sink(self.x); // $ hasTaintFlow=t10.1 + x = "safe" + self.x += sink(x) + source("t10.1") + sink(x) // $ hasTaintFlow=t10.1 + sink(self.x) // $ hasTaintFlow=t10.1 } func t11() { - self.x = "safe"; - x += sink(x) + source("t11.1"); - sink(x); // $ hasTaintFlow=t11.1 - sink(self.x); // $ hasTaintFlow=t11.1 + self.x = "safe" + x += sink(x) + source("t11.1") + sink(x) // $ hasTaintFlow=t11.1 + sink(self.x) // $ hasTaintFlow=t11.1 } func t12() { - self.x = "safe"; - self.x += sink(x) + source("t12.1"); - sink(x); // $ hasTaintFlow=t12.1 - sink(self.x); // $ hasTaintFlow=t12.1 + self.x = "safe" + self.x += sink(x) + source("t12.1") + sink(x) // $ hasTaintFlow=t12.1 + sink(self.x) // $ hasTaintFlow=t12.1 } } diff --git a/unified/ql/test/library-tests/dataflow/test.expected b/unified/ql/test/library-tests/dataflow/test.expected index fb4090d3e62f..09bfb86d7540 100644 --- a/unified/ql/test/library-tests/dataflow/test.expected +++ b/unified/ql/test/library-tests/dataflow/test.expected @@ -1,372 +1,462 @@ models edges -| implicit-self.swift:11:9:11:12 | [post] self [x] | implicit-self.swift:12:14:12:17 | self [x] | provenance | | -| implicit-self.swift:11:9:11:14 | ... .x | implicit-self.swift:11:9:11:12 | [post] self [x] | provenance | | -| implicit-self.swift:11:18:11:31 | source(...) | implicit-self.swift:11:9:11:14 | ... .x | provenance | | -| implicit-self.swift:12:14:12:17 | self [x] | implicit-self.swift:12:14:12:19 | ... .x | provenance | | -| implicit-self.swift:17:9:17:9 | x | implicit-self.swift:18:14:18:14 | x | provenance | | -| implicit-self.swift:17:13:17:26 | source(...) | implicit-self.swift:17:9:17:9 | x | provenance | | -| implicit-self.swift:23:9:23:9 | x | implicit-self.swift:24:14:24:17 | self [x] | provenance | | -| implicit-self.swift:23:13:23:26 | source(...) | implicit-self.swift:23:9:23:9 | x | provenance | | -| implicit-self.swift:24:14:24:17 | self [x] | implicit-self.swift:24:14:24:19 | ... .x | provenance | | -| implicit-self.swift:29:9:29:12 | [post] self [x] | implicit-self.swift:30:14:30:14 | x | provenance | | -| implicit-self.swift:29:9:29:14 | ... .x | implicit-self.swift:29:9:29:12 | [post] self [x] | provenance | | -| implicit-self.swift:29:18:29:31 | source(...) | implicit-self.swift:29:9:29:14 | ... .x | provenance | | -| implicit-self.swift:35:9:35:12 | [post] self [box, x] | implicit-self.swift:36:14:36:17 | self [box, x] | provenance | | -| implicit-self.swift:35:9:35:16 | [post] ... .box [x] | implicit-self.swift:35:9:35:12 | [post] self [box, x] | provenance | | -| implicit-self.swift:35:9:35:18 | ... .x | implicit-self.swift:35:9:35:16 | [post] ... .box [x] | provenance | | -| implicit-self.swift:35:22:35:35 | source(...) | implicit-self.swift:35:9:35:18 | ... .x | provenance | | -| implicit-self.swift:36:14:36:17 | self [box, x] | implicit-self.swift:36:14:36:21 | ... .box [x] | provenance | | -| implicit-self.swift:36:14:36:21 | ... .box [x] | implicit-self.swift:36:14:36:23 | ... .x | provenance | | -| implicit-self.swift:41:9:41:11 | [post] box [x] | implicit-self.swift:42:14:42:16 | box [x] | provenance | | -| implicit-self.swift:41:9:41:13 | ... .x | implicit-self.swift:41:9:41:11 | [post] box [x] | provenance | | -| implicit-self.swift:41:17:41:30 | source(...) | implicit-self.swift:41:9:41:13 | ... .x | provenance | | -| implicit-self.swift:42:14:42:16 | box [x] | implicit-self.swift:42:14:42:18 | ... .x | provenance | | -| implicit-self.swift:47:9:47:11 | [post] box [x] | implicit-self.swift:48:14:48:17 | self [box, x] | provenance | | -| implicit-self.swift:47:9:47:13 | ... .x | implicit-self.swift:47:9:47:11 | [post] box [x] | provenance | | -| implicit-self.swift:47:17:47:30 | source(...) | implicit-self.swift:47:9:47:13 | ... .x | provenance | | -| implicit-self.swift:48:14:48:17 | self [box, x] | implicit-self.swift:48:14:48:21 | ... .box [x] | provenance | | -| implicit-self.swift:48:14:48:21 | ... .box [x] | implicit-self.swift:48:14:48:23 | ... .x | provenance | | -| implicit-self.swift:53:9:53:12 | [post] self [box, x] | implicit-self.swift:54:14:54:16 | box [x] | provenance | | -| implicit-self.swift:53:9:53:16 | [post] ... .box [x] | implicit-self.swift:53:9:53:12 | [post] self [box, x] | provenance | | -| implicit-self.swift:53:9:53:18 | ... .x | implicit-self.swift:53:9:53:16 | [post] ... .box [x] | provenance | | -| implicit-self.swift:53:22:53:35 | source(...) | implicit-self.swift:53:9:53:18 | ... .x | provenance | | -| implicit-self.swift:54:14:54:16 | box [x] | implicit-self.swift:54:14:54:18 | ... .x | provenance | | -| implicit-self.swift:59:9:59:9 | [incoming] x | implicit-self.swift:60:14:60:14 | x | provenance | | -| implicit-self.swift:59:9:59:9 | [incoming] x | implicit-self.swift:61:14:61:17 | self [x] | provenance | | -| implicit-self.swift:59:24:59:37 | source(...) | implicit-self.swift:59:9:59:9 | [incoming] x | provenance | | -| implicit-self.swift:61:14:61:17 | self [x] | implicit-self.swift:61:14:61:19 | ... .x | provenance | | -| implicit-self.swift:66:9:66:12 | [post] self [x] | implicit-self.swift:67:14:67:14 | x | provenance | | -| implicit-self.swift:66:9:66:12 | [post] self [x] | implicit-self.swift:68:14:68:17 | self [x] | provenance | | -| implicit-self.swift:66:9:66:14 | [incoming] ... .x | implicit-self.swift:66:9:66:12 | [post] self [x] | provenance | | -| implicit-self.swift:66:29:66:43 | source(...) | implicit-self.swift:66:9:66:14 | [incoming] ... .x | provenance | | -| implicit-self.swift:68:14:68:17 | self [x] | implicit-self.swift:68:14:68:19 | ... .x | provenance | | -| implicit-self.swift:73:9:73:9 | [incoming] x | implicit-self.swift:74:14:74:14 | x | provenance | | -| implicit-self.swift:73:9:73:9 | [incoming] x | implicit-self.swift:75:14:75:17 | self [x] | provenance | | -| implicit-self.swift:73:24:73:38 | source(...) | implicit-self.swift:73:9:73:9 | [incoming] x | provenance | | -| implicit-self.swift:75:14:75:17 | self [x] | implicit-self.swift:75:14:75:19 | ... .x | provenance | | -| implicit-self.swift:80:9:80:12 | [post] self [x] | implicit-self.swift:81:14:81:14 | x | provenance | | -| implicit-self.swift:80:9:80:12 | [post] self [x] | implicit-self.swift:82:14:82:17 | self [x] | provenance | | -| implicit-self.swift:80:9:80:14 | [incoming] ... .x | implicit-self.swift:80:9:80:12 | [post] self [x] | provenance | | -| implicit-self.swift:80:29:80:43 | source(...) | implicit-self.swift:80:9:80:14 | [incoming] ... .x | provenance | | -| implicit-self.swift:82:14:82:17 | self [x] | implicit-self.swift:82:14:82:19 | ... .x | provenance | | -| test.swift:6:10:6:23 | source(...) | test.swift:6:10:6:32 | ... + ... | provenance | | -| test.swift:7:19:7:32 | source(...) | test.swift:7:10:7:32 | ... + ... | provenance | | -| test.swift:9:13:9:26 | source(...) | test.swift:9:10:9:33 | StringInterpolationExpr | provenance | | -| test.swift:10:18:10:31 | source(...) | test.swift:10:10:10:33 | StringInterpolationExpr | provenance | | -| test.swift:11:18:11:31 | source(...) | test.swift:11:10:11:38 | StringInterpolationExpr | provenance | | -| test.swift:16:10:16:33 | TupleExpr [0] | test.swift:16:10:16:35 | ... .0 | provenance | | -| test.swift:16:11:16:25 | source(...) | test.swift:16:10:16:33 | TupleExpr [0] | provenance | | -| test.swift:19:10:19:33 | TupleExpr [1] | test.swift:19:10:19:35 | ... .1 | provenance | | -| test.swift:19:19:19:32 | source(...) | test.swift:19:10:19:33 | TupleExpr [1] | provenance | | -| test.swift:23:9:23:9 | a | test.swift:24:10:24:10 | a | provenance | | -| test.swift:23:13:23:26 | source(...) | test.swift:23:9:23:9 | a | provenance | | -| test.swift:28:9:28:14 | TupleExpr [0] | test.swift:28:10:28:10 | a | provenance | | -| test.swift:28:10:28:10 | a | test.swift:29:10:29:10 | a | provenance | | -| test.swift:28:18:28:41 | TupleExpr [0] | test.swift:28:9:28:14 | TupleExpr [0] | provenance | | -| test.swift:28:19:28:33 | source(...) | test.swift:28:18:28:41 | TupleExpr [0] | provenance | | -| test.swift:32:9:32:14 | TupleExpr [1] | test.swift:32:13:32:13 | d | provenance | | -| test.swift:32:13:32:13 | d | test.swift:34:10:34:10 | d | provenance | | -| test.swift:32:18:32:41 | TupleExpr [1] | test.swift:32:9:32:14 | TupleExpr [1] | provenance | | -| test.swift:32:27:32:40 | source(...) | test.swift:32:18:32:41 | TupleExpr [1] | provenance | | -| test.swift:38:9:38:9 | a | test.swift:39:10:39:10 | a | provenance | | -| test.swift:38:13:38:26 | source(...) | test.swift:38:9:38:9 | a | provenance | | -| test.swift:46:5:46:9 | [post] tuple [0] | test.swift:47:10:47:14 | tuple [0] | provenance | | -| test.swift:46:5:46:11 | ... .0 | test.swift:46:5:46:9 | [post] tuple [0] | provenance | | -| test.swift:46:15:46:28 | source(...) | test.swift:46:5:46:11 | ... .0 | provenance | | -| test.swift:47:10:47:14 | tuple [0] | test.swift:47:10:47:16 | ... .0 | provenance | | -| test.swift:53:5:53:14 | [post] deep_tuple [1, 0] | test.swift:58:10:58:19 | deep_tuple [1, 0] | provenance | | -| test.swift:53:5:53:16 | [post] ... .1 [0] | test.swift:53:5:53:14 | [post] deep_tuple [1, 0] | provenance | | -| test.swift:53:5:53:18 | ... .0 | test.swift:53:5:53:16 | [post] ... .1 [0] | provenance | | -| test.swift:53:22:53:35 | source(...) | test.swift:53:5:53:18 | ... .0 | provenance | | -| test.swift:58:10:58:19 | deep_tuple [1, 0] | test.swift:58:10:58:21 | ... .1 [0] | provenance | | -| test.swift:58:10:58:21 | ... .1 [0] | test.swift:58:10:58:23 | ... .0 | provenance | | -| test.swift:64:5:64:16 | TupleExpr [0] | test.swift:64:6:64:12 | ... .1 | provenance | | -| test.swift:64:6:64:10 | [post] tuple [1] | test.swift:66:10:66:14 | tuple [1] | provenance | | -| test.swift:64:6:64:12 | ... .1 | test.swift:64:6:64:10 | [post] tuple [1] | provenance | | -| test.swift:64:20:64:51 | TupleExpr [0] | test.swift:64:5:64:16 | TupleExpr [0] | provenance | | -| test.swift:64:21:64:35 | source(...) | test.swift:64:20:64:51 | TupleExpr [0] | provenance | | -| test.swift:66:10:66:14 | tuple [1] | test.swift:66:10:66:16 | ... .1 | provenance | | -| test.swift:74:5:74:9 | [post] tuple [0] | test.swift:75:10:75:14 | tuple [0] | provenance | | -| test.swift:74:5:74:11 | ... .0 | test.swift:74:5:74:9 | [post] tuple [0] | provenance | | -| test.swift:74:15:74:29 | source(...) | test.swift:74:5:74:11 | ... .0 | provenance | | -| test.swift:75:10:75:14 | tuple [0] | test.swift:75:10:75:16 | ... .0 | provenance | | -| test.swift:86:9:86:9 | x | test.swift:90:10:90:10 | x | provenance | | -| test.swift:86:9:86:9 | x | test.swift:99:14:99:14 | x | provenance | | -| test.swift:86:13:86:27 | source(...) | test.swift:86:9:86:9 | x | provenance | | -| test.swift:94:9:94:9 | y | test.swift:96:10:96:10 | y | provenance | | -| test.swift:94:9:94:9 | y | test.swift:100:14:100:14 | y | provenance | | -| test.swift:94:13:94:27 | source(...) | test.swift:94:9:94:9 | y | provenance | | -| test.swift:107:9:107:13 | [post] tuple [0] | test.swift:112:10:112:14 | tuple [0] | provenance | | -| test.swift:107:9:107:15 | ... .0 | test.swift:107:9:107:13 | [post] tuple [0] | provenance | | -| test.swift:107:19:107:33 | source(...) | test.swift:107:9:107:15 | ... .0 | provenance | | -| test.swift:112:10:112:14 | tuple [0] | test.swift:112:10:112:16 | ... .0 | provenance | | -| test.swift:117:9:117:13 | tuple [0] | test.swift:120:17:120:21 | tuple [0] | provenance | | -| test.swift:117:9:117:13 | tuple [1] | test.swift:120:17:120:21 | tuple [1] | provenance | | -| test.swift:117:17:117:50 | TupleExpr [0] | test.swift:117:9:117:13 | tuple [0] | provenance | | -| test.swift:117:17:117:50 | TupleExpr [1] | test.swift:117:9:117:13 | tuple [1] | provenance | | -| test.swift:117:18:117:33 | source(...) | test.swift:117:17:117:50 | TupleExpr [0] | provenance | | -| test.swift:117:35:117:49 | source(...) | test.swift:117:17:117:50 | TupleExpr [1] | provenance | | -| test.swift:120:9:120:13 | TupleExpr [0] | test.swift:120:10:120:10 | a | provenance | | -| test.swift:120:9:120:13 | TupleExpr [1] | test.swift:120:12:120:12 | b | provenance | | -| test.swift:120:10:120:10 | a | test.swift:125:10:125:10 | a | provenance | | -| test.swift:120:12:120:12 | b | test.swift:126:10:126:10 | b | provenance | | -| test.swift:120:17:120:21 | tuple [0] | test.swift:120:9:120:13 | TupleExpr [0] | provenance | | -| test.swift:120:17:120:21 | tuple [1] | test.swift:120:9:120:13 | TupleExpr [1] | provenance | | -| test.swift:131:5:131:5 | a | test.swift:132:10:132:10 | a | provenance | | -| test.swift:131:19:131:33 | source(...) | test.swift:131:5:131:5 | a | provenance | | -| test.swift:137:5:137:5 | [incoming] a | test.swift:138:10:138:10 | a | provenance | | -| test.swift:137:10:137:24 | source(...) | test.swift:137:5:137:5 | [incoming] a | provenance | | -| test.swift:143:5:143:5 | [incoming] a | test.swift:144:10:144:10 | a | provenance | | -| test.swift:143:20:143:34 | source(...) | test.swift:143:5:143:5 | [incoming] a | provenance | | -| test.swift:149:5:149:5 | [post] a [0] | test.swift:150:10:150:10 | a [0] | provenance | | -| test.swift:149:5:149:7 | ... .0 | test.swift:149:5:149:5 | [post] a [0] | provenance | | -| test.swift:149:23:149:37 | source(...) | test.swift:149:5:149:7 | ... .0 | provenance | | -| test.swift:150:10:150:10 | a [0] | test.swift:150:10:150:12 | ... .0 | provenance | | -| test.swift:156:5:156:12 | TupleExpr [0] | test.swift:156:6:156:8 | ... .0 | provenance | | -| test.swift:156:6:156:6 | [post] a [0] | test.swift:157:10:157:10 | a [0] | provenance | | -| test.swift:156:6:156:8 | ... .0 | test.swift:156:6:156:6 | [post] a [0] | provenance | | -| test.swift:156:16:156:61 | TupleExpr [0] | test.swift:156:5:156:12 | TupleExpr [0] | provenance | | -| test.swift:156:17:156:43 | ... + ... | test.swift:156:16:156:61 | TupleExpr [0] | provenance | | -| test.swift:156:29:156:43 | source(...) | test.swift:156:17:156:43 | ... + ... | provenance | | -| test.swift:157:10:157:10 | a [0] | test.swift:157:10:157:12 | ... .0 | provenance | | -| test.swift:164:5:164:10 | TupleExpr [0] | test.swift:164:6:164:6 | a | provenance | | -| test.swift:164:5:164:10 | TupleExpr [1] | test.swift:164:9:164:9 | b | provenance | | -| test.swift:164:6:164:6 | a | test.swift:165:10:165:10 | a | provenance | | -| test.swift:164:9:164:9 | b | test.swift:166:10:166:10 | b | provenance | | -| test.swift:164:14:164:67 | TupleExpr [0] | test.swift:164:5:164:10 | TupleExpr [0] | provenance | | -| test.swift:164:14:164:67 | TupleExpr [1] | test.swift:164:5:164:10 | TupleExpr [1] | provenance | | -| test.swift:164:15:164:39 | ... + ... | test.swift:164:14:164:67 | TupleExpr [0] | provenance | | -| test.swift:164:25:164:39 | source(...) | test.swift:164:15:164:39 | ... + ... | provenance | | -| test.swift:164:42:164:66 | ... + ... | test.swift:164:14:164:67 | TupleExpr [1] | provenance | | -| test.swift:164:52:164:66 | source(...) | test.swift:164:42:164:66 | ... + ... | provenance | | +| calls.swift:7:19:7:19 | x | calls.swift:8:14:8:14 | x | provenance | | +| calls.swift:10:12:10:25 | source(...) | calls.swift:7:19:7:19 | x | provenance | | +| calls.swift:15:16:15:29 | source(...) | calls.swift:17:10:17:17 | target(...) | provenance | | +| calls.swift:21:17:21:17 | x | calls.swift:22:14:22:14 | x | provenance | | +| calls.swift:24:12:24:28 | source(...) | calls.swift:21:17:21:17 | x | provenance | | +| calls.swift:28:19:28:19 | x | calls.swift:29:16:29:16 | x | provenance | | +| calls.swift:29:16:29:16 | x | calls.swift:29:16:29:24 | ... + ... | provenance | | +| calls.swift:31:17:31:30 | source(...) | calls.swift:28:19:28:19 | x | provenance | | +| calls.swift:31:17:31:30 | source(...) | calls.swift:31:10:31:31 | target(...) | provenance | | +| calls.swift:32:17:32:30 | source(...) | calls.swift:28:19:28:19 | x | provenance | | +| calls.swift:32:17:32:30 | source(...) | calls.swift:32:10:32:31 | target(...) | provenance | | +| calls.swift:37:23:37:23 | x | calls.swift:38:14:38:14 | x | provenance | | +| calls.swift:40:13:40:32 | source(...) | calls.swift:37:23:37:23 | x | provenance | | +| calls.swift:42:18:42:21 | name | calls.swift:43:14:43:17 | name | provenance | | +| calls.swift:45:13:45:32 | source(...) | calls.swift:42:18:42:21 | name | provenance | | +| calls.swift:49:19:49:19 | x | calls.swift:50:14:50:14 | x | provenance | | +| calls.swift:49:32:49:32 | y | calls.swift:51:14:51:14 | y | provenance | | +| calls.swift:53:12:53:26 | source(...) | calls.swift:49:19:49:19 | x | provenance | | +| calls.swift:53:28:53:41 | source(...) | calls.swift:49:32:49:32 | y | provenance | | +| calls.swift:61:19:61:19 | x [Return] [field] | calls.swift:66:12:66:12 | [post] b [field] | provenance | | +| calls.swift:62:9:62:9 | [post] x [field] | calls.swift:61:19:61:19 | x [Return] [field] | provenance | | +| calls.swift:62:9:62:15 | ... .field | calls.swift:62:9:62:9 | [post] x [field] | provenance | | +| calls.swift:62:19:62:32 | source(...) | calls.swift:62:9:62:15 | ... .field | provenance | | +| calls.swift:66:12:66:12 | [post] b [field] | calls.swift:67:10:67:10 | b [field] | provenance | | +| calls.swift:67:10:67:10 | b [field] | calls.swift:67:10:67:16 | ... .field | provenance | | +| calls.swift:75:13:75:17 | field | calls.swift:81:18:81:22 | field | provenance | | +| calls.swift:75:13:75:17 | field | calls.swift:87:18:87:21 | self [field] | provenance | | +| calls.swift:75:13:75:17 | field | calls.swift:105:18:105:22 | field | provenance | | +| calls.swift:75:13:75:17 | field | calls.swift:111:18:111:21 | self [field] | provenance | | +| calls.swift:75:21:75:34 | source(...) | calls.swift:75:13:75:17 | field | provenance | | +| calls.swift:87:18:87:21 | self [field] | calls.swift:87:18:87:27 | ... .field | provenance | | +| calls.swift:111:18:111:21 | self [field] | calls.swift:111:18:111:27 | ... .field | provenance | | +| implicit-self.swift:16:9:16:12 | [post] self [x] | implicit-self.swift:17:14:17:17 | self [x] | provenance | | +| implicit-self.swift:16:9:16:14 | ... .x | implicit-self.swift:16:9:16:12 | [post] self [x] | provenance | | +| implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:16:9:16:14 | ... .x | provenance | | +| implicit-self.swift:17:14:17:17 | self [x] | implicit-self.swift:17:14:17:19 | ... .x | provenance | | +| implicit-self.swift:22:9:22:9 | x | implicit-self.swift:23:14:23:14 | x | provenance | | +| implicit-self.swift:22:13:22:26 | source(...) | implicit-self.swift:22:9:22:9 | x | provenance | | +| implicit-self.swift:28:9:28:9 | x | implicit-self.swift:29:14:29:17 | self [x] | provenance | | +| implicit-self.swift:28:13:28:26 | source(...) | implicit-self.swift:28:9:28:9 | x | provenance | | +| implicit-self.swift:29:14:29:17 | self [x] | implicit-self.swift:29:14:29:19 | ... .x | provenance | | +| implicit-self.swift:34:9:34:12 | [post] self [x] | implicit-self.swift:35:14:35:14 | x | provenance | | +| implicit-self.swift:34:9:34:14 | ... .x | implicit-self.swift:34:9:34:12 | [post] self [x] | provenance | | +| implicit-self.swift:34:18:34:31 | source(...) | implicit-self.swift:34:9:34:14 | ... .x | provenance | | +| implicit-self.swift:40:9:40:12 | [post] self [box, x] | implicit-self.swift:41:14:41:17 | self [box, x] | provenance | | +| implicit-self.swift:40:9:40:16 | [post] ... .box [x] | implicit-self.swift:40:9:40:12 | [post] self [box, x] | provenance | | +| implicit-self.swift:40:9:40:18 | ... .x | implicit-self.swift:40:9:40:16 | [post] ... .box [x] | provenance | | +| implicit-self.swift:40:22:40:35 | source(...) | implicit-self.swift:40:9:40:18 | ... .x | provenance | | +| implicit-self.swift:41:14:41:17 | self [box, x] | implicit-self.swift:41:14:41:21 | ... .box [x] | provenance | | +| implicit-self.swift:41:14:41:21 | ... .box [x] | implicit-self.swift:41:14:41:23 | ... .x | provenance | | +| implicit-self.swift:46:9:46:11 | [post] box [x] | implicit-self.swift:47:14:47:16 | box [x] | provenance | | +| implicit-self.swift:46:9:46:13 | ... .x | implicit-self.swift:46:9:46:11 | [post] box [x] | provenance | | +| implicit-self.swift:46:17:46:30 | source(...) | implicit-self.swift:46:9:46:13 | ... .x | provenance | | +| implicit-self.swift:47:14:47:16 | box [x] | implicit-self.swift:47:14:47:18 | ... .x | provenance | | +| implicit-self.swift:52:9:52:11 | [post] box [x] | implicit-self.swift:53:14:53:17 | self [box, x] | provenance | | +| implicit-self.swift:52:9:52:13 | ... .x | implicit-self.swift:52:9:52:11 | [post] box [x] | provenance | | +| implicit-self.swift:52:17:52:30 | source(...) | implicit-self.swift:52:9:52:13 | ... .x | provenance | | +| implicit-self.swift:53:14:53:17 | self [box, x] | implicit-self.swift:53:14:53:21 | ... .box [x] | provenance | | +| implicit-self.swift:53:14:53:21 | ... .box [x] | implicit-self.swift:53:14:53:23 | ... .x | provenance | | +| implicit-self.swift:58:9:58:12 | [post] self [box, x] | implicit-self.swift:59:14:59:16 | box [x] | provenance | | +| implicit-self.swift:58:9:58:16 | [post] ... .box [x] | implicit-self.swift:58:9:58:12 | [post] self [box, x] | provenance | | +| implicit-self.swift:58:9:58:18 | ... .x | implicit-self.swift:58:9:58:16 | [post] ... .box [x] | provenance | | +| implicit-self.swift:58:22:58:35 | source(...) | implicit-self.swift:58:9:58:18 | ... .x | provenance | | +| implicit-self.swift:59:14:59:16 | box [x] | implicit-self.swift:59:14:59:18 | ... .x | provenance | | +| implicit-self.swift:64:9:64:9 | [incoming] x | implicit-self.swift:65:14:65:14 | x | provenance | | +| implicit-self.swift:64:9:64:9 | [incoming] x | implicit-self.swift:66:14:66:17 | self [x] | provenance | | +| implicit-self.swift:64:24:64:37 | source(...) | implicit-self.swift:64:9:64:9 | [incoming] x | provenance | | +| implicit-self.swift:66:14:66:17 | self [x] | implicit-self.swift:66:14:66:19 | ... .x | provenance | | +| implicit-self.swift:71:9:71:12 | [post] self [x] | implicit-self.swift:72:14:72:14 | x | provenance | | +| implicit-self.swift:71:9:71:12 | [post] self [x] | implicit-self.swift:73:14:73:17 | self [x] | provenance | | +| implicit-self.swift:71:9:71:14 | [incoming] ... .x | implicit-self.swift:71:9:71:12 | [post] self [x] | provenance | | +| implicit-self.swift:71:29:71:43 | source(...) | implicit-self.swift:71:9:71:14 | [incoming] ... .x | provenance | | +| implicit-self.swift:73:14:73:17 | self [x] | implicit-self.swift:73:14:73:19 | ... .x | provenance | | +| implicit-self.swift:78:9:78:9 | [incoming] x | implicit-self.swift:79:14:79:14 | x | provenance | | +| implicit-self.swift:78:9:78:9 | [incoming] x | implicit-self.swift:80:14:80:17 | self [x] | provenance | | +| implicit-self.swift:78:24:78:38 | source(...) | implicit-self.swift:78:9:78:9 | [incoming] x | provenance | | +| implicit-self.swift:80:14:80:17 | self [x] | implicit-self.swift:80:14:80:19 | ... .x | provenance | | +| implicit-self.swift:85:9:85:12 | [post] self [x] | implicit-self.swift:86:14:86:14 | x | provenance | | +| implicit-self.swift:85:9:85:12 | [post] self [x] | implicit-self.swift:87:14:87:17 | self [x] | provenance | | +| implicit-self.swift:85:9:85:14 | [incoming] ... .x | implicit-self.swift:85:9:85:12 | [post] self [x] | provenance | | +| implicit-self.swift:85:29:85:43 | source(...) | implicit-self.swift:85:9:85:14 | [incoming] ... .x | provenance | | +| implicit-self.swift:87:14:87:17 | self [x] | implicit-self.swift:87:14:87:19 | ... .x | provenance | | +| test.swift:17:10:17:23 | source(...) | test.swift:17:10:17:32 | ... + ... | provenance | | +| test.swift:18:19:18:32 | source(...) | test.swift:18:10:18:32 | ... + ... | provenance | | +| test.swift:20:13:20:26 | source(...) | test.swift:20:10:20:33 | StringInterpolationExpr | provenance | | +| test.swift:21:18:21:31 | source(...) | test.swift:21:10:21:33 | StringInterpolationExpr | provenance | | +| test.swift:22:18:22:31 | source(...) | test.swift:22:10:22:38 | StringInterpolationExpr | provenance | | +| test.swift:27:10:27:33 | TupleExpr [0] | test.swift:27:10:27:35 | ... .0 | provenance | | +| test.swift:27:11:27:25 | source(...) | test.swift:27:10:27:33 | TupleExpr [0] | provenance | | +| test.swift:30:10:30:33 | TupleExpr [1] | test.swift:30:10:30:35 | ... .1 | provenance | | +| test.swift:30:19:30:32 | source(...) | test.swift:30:10:30:33 | TupleExpr [1] | provenance | | +| test.swift:34:9:34:9 | a | test.swift:35:10:35:10 | a | provenance | | +| test.swift:34:13:34:26 | source(...) | test.swift:34:9:34:9 | a | provenance | | +| test.swift:39:9:39:14 | TupleExpr [0] | test.swift:39:10:39:10 | a | provenance | | +| test.swift:39:10:39:10 | a | test.swift:40:10:40:10 | a | provenance | | +| test.swift:39:18:39:41 | TupleExpr [0] | test.swift:39:9:39:14 | TupleExpr [0] | provenance | | +| test.swift:39:19:39:33 | source(...) | test.swift:39:18:39:41 | TupleExpr [0] | provenance | | +| test.swift:43:9:43:14 | TupleExpr [1] | test.swift:43:13:43:13 | d | provenance | | +| test.swift:43:13:43:13 | d | test.swift:45:10:45:10 | d | provenance | | +| test.swift:43:18:43:41 | TupleExpr [1] | test.swift:43:9:43:14 | TupleExpr [1] | provenance | | +| test.swift:43:27:43:40 | source(...) | test.swift:43:18:43:41 | TupleExpr [1] | provenance | | +| test.swift:49:9:49:9 | a | test.swift:50:10:50:10 | a | provenance | | +| test.swift:49:13:49:26 | source(...) | test.swift:49:9:49:9 | a | provenance | | +| test.swift:57:5:57:9 | [post] tuple [0] | test.swift:58:10:58:14 | tuple [0] | provenance | | +| test.swift:57:5:57:11 | ... .0 | test.swift:57:5:57:9 | [post] tuple [0] | provenance | | +| test.swift:57:15:57:28 | source(...) | test.swift:57:5:57:11 | ... .0 | provenance | | +| test.swift:58:10:58:14 | tuple [0] | test.swift:58:10:58:16 | ... .0 | provenance | | +| test.swift:64:5:64:14 | [post] deep_tuple [1, 0] | test.swift:69:10:69:19 | deep_tuple [1, 0] | provenance | | +| test.swift:64:5:64:16 | [post] ... .1 [0] | test.swift:64:5:64:14 | [post] deep_tuple [1, 0] | provenance | | +| test.swift:64:5:64:18 | ... .0 | test.swift:64:5:64:16 | [post] ... .1 [0] | provenance | | +| test.swift:64:22:64:35 | source(...) | test.swift:64:5:64:18 | ... .0 | provenance | | +| test.swift:69:10:69:19 | deep_tuple [1, 0] | test.swift:69:10:69:21 | ... .1 [0] | provenance | | +| test.swift:69:10:69:21 | ... .1 [0] | test.swift:69:10:69:23 | ... .0 | provenance | | +| test.swift:75:5:75:16 | TupleExpr [0] | test.swift:75:6:75:12 | ... .1 | provenance | | +| test.swift:75:6:75:10 | [post] tuple [1] | test.swift:77:10:77:14 | tuple [1] | provenance | | +| test.swift:75:6:75:12 | ... .1 | test.swift:75:6:75:10 | [post] tuple [1] | provenance | | +| test.swift:75:20:75:51 | TupleExpr [0] | test.swift:75:5:75:16 | TupleExpr [0] | provenance | | +| test.swift:75:21:75:35 | source(...) | test.swift:75:20:75:51 | TupleExpr [0] | provenance | | +| test.swift:77:10:77:14 | tuple [1] | test.swift:77:10:77:16 | ... .1 | provenance | | +| test.swift:85:5:85:9 | [post] tuple [0] | test.swift:86:10:86:14 | tuple [0] | provenance | | +| test.swift:85:5:85:11 | ... .0 | test.swift:85:5:85:9 | [post] tuple [0] | provenance | | +| test.swift:85:15:85:29 | source(...) | test.swift:85:5:85:11 | ... .0 | provenance | | +| test.swift:86:10:86:14 | tuple [0] | test.swift:86:10:86:16 | ... .0 | provenance | | +| test.swift:97:9:97:9 | x | test.swift:101:10:101:10 | x | provenance | | +| test.swift:97:9:97:9 | x | test.swift:110:14:110:14 | x | provenance | | +| test.swift:97:13:97:27 | source(...) | test.swift:97:9:97:9 | x | provenance | | +| test.swift:105:9:105:9 | y | test.swift:107:10:107:10 | y | provenance | | +| test.swift:105:9:105:9 | y | test.swift:111:14:111:14 | y | provenance | | +| test.swift:105:13:105:27 | source(...) | test.swift:105:9:105:9 | y | provenance | | +| test.swift:118:9:118:13 | [post] tuple [0] | test.swift:123:10:123:14 | tuple [0] | provenance | | +| test.swift:118:9:118:15 | ... .0 | test.swift:118:9:118:13 | [post] tuple [0] | provenance | | +| test.swift:118:19:118:33 | source(...) | test.swift:118:9:118:15 | ... .0 | provenance | | +| test.swift:123:10:123:14 | tuple [0] | test.swift:123:10:123:16 | ... .0 | provenance | | +| test.swift:128:9:128:13 | tuple [0] | test.swift:131:18:131:22 | tuple [0] | provenance | | +| test.swift:128:9:128:13 | tuple [1] | test.swift:131:18:131:22 | tuple [1] | provenance | | +| test.swift:128:17:128:50 | TupleExpr [0] | test.swift:128:9:128:13 | tuple [0] | provenance | | +| test.swift:128:17:128:50 | TupleExpr [1] | test.swift:128:9:128:13 | tuple [1] | provenance | | +| test.swift:128:18:128:33 | source(...) | test.swift:128:17:128:50 | TupleExpr [0] | provenance | | +| test.swift:128:35:128:49 | source(...) | test.swift:128:17:128:50 | TupleExpr [1] | provenance | | +| test.swift:131:9:131:14 | TupleExpr [0] | test.swift:131:10:131:10 | a | provenance | | +| test.swift:131:9:131:14 | TupleExpr [1] | test.swift:131:13:131:13 | b | provenance | | +| test.swift:131:10:131:10 | a | test.swift:136:10:136:10 | a | provenance | | +| test.swift:131:13:131:13 | b | test.swift:137:10:137:10 | b | provenance | | +| test.swift:131:18:131:22 | tuple [0] | test.swift:131:9:131:14 | TupleExpr [0] | provenance | | +| test.swift:131:18:131:22 | tuple [1] | test.swift:131:9:131:14 | TupleExpr [1] | provenance | | +| test.swift:142:5:142:5 | a | test.swift:143:10:143:10 | a | provenance | | +| test.swift:142:19:142:33 | source(...) | test.swift:142:5:142:5 | a | provenance | | +| test.swift:148:5:148:5 | [incoming] a | test.swift:149:10:149:10 | a | provenance | | +| test.swift:148:10:148:24 | source(...) | test.swift:148:5:148:5 | [incoming] a | provenance | | +| test.swift:154:5:154:5 | [incoming] a | test.swift:155:10:155:10 | a | provenance | | +| test.swift:154:20:154:34 | source(...) | test.swift:154:5:154:5 | [incoming] a | provenance | | +| test.swift:160:5:160:5 | [post] a [0] | test.swift:161:10:161:10 | a [0] | provenance | | +| test.swift:160:5:160:7 | ... .0 | test.swift:160:5:160:5 | [post] a [0] | provenance | | +| test.swift:160:23:160:37 | source(...) | test.swift:160:5:160:7 | ... .0 | provenance | | +| test.swift:161:10:161:10 | a [0] | test.swift:161:10:161:12 | ... .0 | provenance | | +| test.swift:167:5:167:12 | TupleExpr [0] | test.swift:167:6:167:8 | ... .0 | provenance | | +| test.swift:167:6:167:6 | [post] a [0] | test.swift:168:10:168:10 | a [0] | provenance | | +| test.swift:167:6:167:8 | ... .0 | test.swift:167:6:167:6 | [post] a [0] | provenance | | +| test.swift:167:16:167:61 | TupleExpr [0] | test.swift:167:5:167:12 | TupleExpr [0] | provenance | | +| test.swift:167:17:167:43 | ... + ... | test.swift:167:16:167:61 | TupleExpr [0] | provenance | | +| test.swift:167:29:167:43 | source(...) | test.swift:167:17:167:43 | ... + ... | provenance | | +| test.swift:168:10:168:10 | a [0] | test.swift:168:10:168:12 | ... .0 | provenance | | +| test.swift:175:5:175:10 | TupleExpr [0] | test.swift:175:6:175:6 | a | provenance | | +| test.swift:175:5:175:10 | TupleExpr [1] | test.swift:175:9:175:9 | b | provenance | | +| test.swift:175:6:175:6 | a | test.swift:176:10:176:10 | a | provenance | | +| test.swift:175:9:175:9 | b | test.swift:177:10:177:10 | b | provenance | | +| test.swift:175:14:175:67 | TupleExpr [0] | test.swift:175:5:175:10 | TupleExpr [0] | provenance | | +| test.swift:175:14:175:67 | TupleExpr [1] | test.swift:175:5:175:10 | TupleExpr [1] | provenance | | +| test.swift:175:15:175:39 | ... + ... | test.swift:175:14:175:67 | TupleExpr [0] | provenance | | +| test.swift:175:25:175:39 | source(...) | test.swift:175:15:175:39 | ... + ... | provenance | | +| test.swift:175:42:175:66 | ... + ... | test.swift:175:14:175:67 | TupleExpr [1] | provenance | | +| test.swift:175:52:175:66 | source(...) | test.swift:175:42:175:66 | ... + ... | provenance | | nodes -| implicit-self.swift:11:9:11:12 | [post] self [x] | semmle.label | [post] self [x] | -| implicit-self.swift:11:9:11:14 | ... .x | semmle.label | ... .x | -| implicit-self.swift:11:18:11:31 | source(...) | semmle.label | source(...) | -| implicit-self.swift:12:14:12:17 | self [x] | semmle.label | self [x] | -| implicit-self.swift:12:14:12:19 | ... .x | semmle.label | ... .x | -| implicit-self.swift:17:9:17:9 | x | semmle.label | x | -| implicit-self.swift:17:13:17:26 | source(...) | semmle.label | source(...) | -| implicit-self.swift:18:14:18:14 | x | semmle.label | x | -| implicit-self.swift:23:9:23:9 | x | semmle.label | x | -| implicit-self.swift:23:13:23:26 | source(...) | semmle.label | source(...) | -| implicit-self.swift:24:14:24:17 | self [x] | semmle.label | self [x] | -| implicit-self.swift:24:14:24:19 | ... .x | semmle.label | ... .x | -| implicit-self.swift:29:9:29:12 | [post] self [x] | semmle.label | [post] self [x] | -| implicit-self.swift:29:9:29:14 | ... .x | semmle.label | ... .x | -| implicit-self.swift:29:18:29:31 | source(...) | semmle.label | source(...) | -| implicit-self.swift:30:14:30:14 | x | semmle.label | x | -| implicit-self.swift:35:9:35:12 | [post] self [box, x] | semmle.label | [post] self [box, x] | -| implicit-self.swift:35:9:35:16 | [post] ... .box [x] | semmle.label | [post] ... .box [x] | -| implicit-self.swift:35:9:35:18 | ... .x | semmle.label | ... .x | -| implicit-self.swift:35:22:35:35 | source(...) | semmle.label | source(...) | -| implicit-self.swift:36:14:36:17 | self [box, x] | semmle.label | self [box, x] | -| implicit-self.swift:36:14:36:21 | ... .box [x] | semmle.label | ... .box [x] | -| implicit-self.swift:36:14:36:23 | ... .x | semmle.label | ... .x | -| implicit-self.swift:41:9:41:11 | [post] box [x] | semmle.label | [post] box [x] | -| implicit-self.swift:41:9:41:13 | ... .x | semmle.label | ... .x | -| implicit-self.swift:41:17:41:30 | source(...) | semmle.label | source(...) | -| implicit-self.swift:42:14:42:16 | box [x] | semmle.label | box [x] | -| implicit-self.swift:42:14:42:18 | ... .x | semmle.label | ... .x | -| implicit-self.swift:47:9:47:11 | [post] box [x] | semmle.label | [post] box [x] | -| implicit-self.swift:47:9:47:13 | ... .x | semmle.label | ... .x | -| implicit-self.swift:47:17:47:30 | source(...) | semmle.label | source(...) | -| implicit-self.swift:48:14:48:17 | self [box, x] | semmle.label | self [box, x] | -| implicit-self.swift:48:14:48:21 | ... .box [x] | semmle.label | ... .box [x] | -| implicit-self.swift:48:14:48:23 | ... .x | semmle.label | ... .x | -| implicit-self.swift:53:9:53:12 | [post] self [box, x] | semmle.label | [post] self [box, x] | -| implicit-self.swift:53:9:53:16 | [post] ... .box [x] | semmle.label | [post] ... .box [x] | -| implicit-self.swift:53:9:53:18 | ... .x | semmle.label | ... .x | -| implicit-self.swift:53:22:53:35 | source(...) | semmle.label | source(...) | -| implicit-self.swift:54:14:54:16 | box [x] | semmle.label | box [x] | -| implicit-self.swift:54:14:54:18 | ... .x | semmle.label | ... .x | -| implicit-self.swift:59:9:59:9 | [incoming] x | semmle.label | [incoming] x | -| implicit-self.swift:59:24:59:37 | source(...) | semmle.label | source(...) | -| implicit-self.swift:60:14:60:14 | x | semmle.label | x | -| implicit-self.swift:61:14:61:17 | self [x] | semmle.label | self [x] | -| implicit-self.swift:61:14:61:19 | ... .x | semmle.label | ... .x | -| implicit-self.swift:66:9:66:12 | [post] self [x] | semmle.label | [post] self [x] | -| implicit-self.swift:66:9:66:14 | [incoming] ... .x | semmle.label | [incoming] ... .x | -| implicit-self.swift:66:29:66:43 | source(...) | semmle.label | source(...) | -| implicit-self.swift:67:14:67:14 | x | semmle.label | x | -| implicit-self.swift:68:14:68:17 | self [x] | semmle.label | self [x] | -| implicit-self.swift:68:14:68:19 | ... .x | semmle.label | ... .x | -| implicit-self.swift:73:9:73:9 | [incoming] x | semmle.label | [incoming] x | -| implicit-self.swift:73:24:73:38 | source(...) | semmle.label | source(...) | -| implicit-self.swift:74:14:74:14 | x | semmle.label | x | -| implicit-self.swift:75:14:75:17 | self [x] | semmle.label | self [x] | -| implicit-self.swift:75:14:75:19 | ... .x | semmle.label | ... .x | -| implicit-self.swift:80:9:80:12 | [post] self [x] | semmle.label | [post] self [x] | -| implicit-self.swift:80:9:80:14 | [incoming] ... .x | semmle.label | [incoming] ... .x | -| implicit-self.swift:80:29:80:43 | source(...) | semmle.label | source(...) | -| implicit-self.swift:81:14:81:14 | x | semmle.label | x | -| implicit-self.swift:82:14:82:17 | self [x] | semmle.label | self [x] | -| implicit-self.swift:82:14:82:19 | ... .x | semmle.label | ... .x | -| test.swift:2:10:2:21 | source(...) | semmle.label | source(...) | -| test.swift:6:10:6:23 | source(...) | semmle.label | source(...) | -| test.swift:6:10:6:32 | ... + ... | semmle.label | ... + ... | -| test.swift:7:10:7:32 | ... + ... | semmle.label | ... + ... | -| test.swift:7:19:7:32 | source(...) | semmle.label | source(...) | -| test.swift:9:10:9:33 | StringInterpolationExpr | semmle.label | StringInterpolationExpr | -| test.swift:9:13:9:26 | source(...) | semmle.label | source(...) | -| test.swift:10:10:10:33 | StringInterpolationExpr | semmle.label | StringInterpolationExpr | -| test.swift:10:18:10:31 | source(...) | semmle.label | source(...) | -| test.swift:11:10:11:38 | StringInterpolationExpr | semmle.label | StringInterpolationExpr | -| test.swift:11:18:11:31 | source(...) | semmle.label | source(...) | -| test.swift:16:10:16:33 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:16:10:16:35 | ... .0 | semmle.label | ... .0 | -| test.swift:16:11:16:25 | source(...) | semmle.label | source(...) | -| test.swift:19:10:19:33 | TupleExpr [1] | semmle.label | TupleExpr [1] | -| test.swift:19:10:19:35 | ... .1 | semmle.label | ... .1 | -| test.swift:19:19:19:32 | source(...) | semmle.label | source(...) | -| test.swift:23:9:23:9 | a | semmle.label | a | -| test.swift:23:13:23:26 | source(...) | semmle.label | source(...) | -| test.swift:24:10:24:10 | a | semmle.label | a | -| test.swift:28:9:28:14 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:28:10:28:10 | a | semmle.label | a | -| test.swift:28:18:28:41 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:28:19:28:33 | source(...) | semmle.label | source(...) | -| test.swift:29:10:29:10 | a | semmle.label | a | -| test.swift:32:9:32:14 | TupleExpr [1] | semmle.label | TupleExpr [1] | -| test.swift:32:13:32:13 | d | semmle.label | d | -| test.swift:32:18:32:41 | TupleExpr [1] | semmle.label | TupleExpr [1] | -| test.swift:32:27:32:40 | source(...) | semmle.label | source(...) | -| test.swift:34:10:34:10 | d | semmle.label | d | -| test.swift:38:9:38:9 | a | semmle.label | a | -| test.swift:38:13:38:26 | source(...) | semmle.label | source(...) | +| calls.swift:7:19:7:19 | x | semmle.label | x | +| calls.swift:8:14:8:14 | x | semmle.label | x | +| calls.swift:10:12:10:25 | source(...) | semmle.label | source(...) | +| calls.swift:15:16:15:29 | source(...) | semmle.label | source(...) | +| calls.swift:17:10:17:17 | target(...) | semmle.label | target(...) | +| calls.swift:21:17:21:17 | x | semmle.label | x | +| calls.swift:22:14:22:14 | x | semmle.label | x | +| calls.swift:24:12:24:28 | source(...) | semmle.label | source(...) | +| calls.swift:28:19:28:19 | x | semmle.label | x | +| calls.swift:29:16:29:16 | x | semmle.label | x | +| calls.swift:29:16:29:24 | ... + ... | semmle.label | ... + ... | +| calls.swift:31:10:31:31 | target(...) | semmle.label | target(...) | +| calls.swift:31:17:31:30 | source(...) | semmle.label | source(...) | +| calls.swift:32:10:32:31 | target(...) | semmle.label | target(...) | +| calls.swift:32:17:32:30 | source(...) | semmle.label | source(...) | +| calls.swift:37:23:37:23 | x | semmle.label | x | +| calls.swift:38:14:38:14 | x | semmle.label | x | +| calls.swift:40:13:40:32 | source(...) | semmle.label | source(...) | +| calls.swift:42:18:42:21 | name | semmle.label | name | +| calls.swift:43:14:43:17 | name | semmle.label | name | +| calls.swift:45:13:45:32 | source(...) | semmle.label | source(...) | +| calls.swift:49:19:49:19 | x | semmle.label | x | +| calls.swift:49:32:49:32 | y | semmle.label | y | +| calls.swift:50:14:50:14 | x | semmle.label | x | +| calls.swift:51:14:51:14 | y | semmle.label | y | +| calls.swift:53:12:53:26 | source(...) | semmle.label | source(...) | +| calls.swift:53:28:53:41 | source(...) | semmle.label | source(...) | +| calls.swift:61:19:61:19 | x [Return] [field] | semmle.label | x [Return] [field] | +| calls.swift:62:9:62:9 | [post] x [field] | semmle.label | [post] x [field] | +| calls.swift:62:9:62:15 | ... .field | semmle.label | ... .field | +| calls.swift:62:19:62:32 | source(...) | semmle.label | source(...) | +| calls.swift:66:12:66:12 | [post] b [field] | semmle.label | [post] b [field] | +| calls.swift:67:10:67:10 | b [field] | semmle.label | b [field] | +| calls.swift:67:10:67:16 | ... .field | semmle.label | ... .field | +| calls.swift:75:13:75:17 | field | semmle.label | field | +| calls.swift:75:21:75:34 | source(...) | semmle.label | source(...) | +| calls.swift:81:18:81:22 | field | semmle.label | field | +| calls.swift:87:18:87:21 | self [field] | semmle.label | self [field] | +| calls.swift:87:18:87:27 | ... .field | semmle.label | ... .field | +| calls.swift:105:18:105:22 | field | semmle.label | field | +| calls.swift:111:18:111:21 | self [field] | semmle.label | self [field] | +| calls.swift:111:18:111:27 | ... .field | semmle.label | ... .field | +| implicit-self.swift:16:9:16:12 | [post] self [x] | semmle.label | [post] self [x] | +| implicit-self.swift:16:9:16:14 | ... .x | semmle.label | ... .x | +| implicit-self.swift:16:18:16:31 | source(...) | semmle.label | source(...) | +| implicit-self.swift:17:14:17:17 | self [x] | semmle.label | self [x] | +| implicit-self.swift:17:14:17:19 | ... .x | semmle.label | ... .x | +| implicit-self.swift:22:9:22:9 | x | semmle.label | x | +| implicit-self.swift:22:13:22:26 | source(...) | semmle.label | source(...) | +| implicit-self.swift:23:14:23:14 | x | semmle.label | x | +| implicit-self.swift:28:9:28:9 | x | semmle.label | x | +| implicit-self.swift:28:13:28:26 | source(...) | semmle.label | source(...) | +| implicit-self.swift:29:14:29:17 | self [x] | semmle.label | self [x] | +| implicit-self.swift:29:14:29:19 | ... .x | semmle.label | ... .x | +| implicit-self.swift:34:9:34:12 | [post] self [x] | semmle.label | [post] self [x] | +| implicit-self.swift:34:9:34:14 | ... .x | semmle.label | ... .x | +| implicit-self.swift:34:18:34:31 | source(...) | semmle.label | source(...) | +| implicit-self.swift:35:14:35:14 | x | semmle.label | x | +| implicit-self.swift:40:9:40:12 | [post] self [box, x] | semmle.label | [post] self [box, x] | +| implicit-self.swift:40:9:40:16 | [post] ... .box [x] | semmle.label | [post] ... .box [x] | +| implicit-self.swift:40:9:40:18 | ... .x | semmle.label | ... .x | +| implicit-self.swift:40:22:40:35 | source(...) | semmle.label | source(...) | +| implicit-self.swift:41:14:41:17 | self [box, x] | semmle.label | self [box, x] | +| implicit-self.swift:41:14:41:21 | ... .box [x] | semmle.label | ... .box [x] | +| implicit-self.swift:41:14:41:23 | ... .x | semmle.label | ... .x | +| implicit-self.swift:46:9:46:11 | [post] box [x] | semmle.label | [post] box [x] | +| implicit-self.swift:46:9:46:13 | ... .x | semmle.label | ... .x | +| implicit-self.swift:46:17:46:30 | source(...) | semmle.label | source(...) | +| implicit-self.swift:47:14:47:16 | box [x] | semmle.label | box [x] | +| implicit-self.swift:47:14:47:18 | ... .x | semmle.label | ... .x | +| implicit-self.swift:52:9:52:11 | [post] box [x] | semmle.label | [post] box [x] | +| implicit-self.swift:52:9:52:13 | ... .x | semmle.label | ... .x | +| implicit-self.swift:52:17:52:30 | source(...) | semmle.label | source(...) | +| implicit-self.swift:53:14:53:17 | self [box, x] | semmle.label | self [box, x] | +| implicit-self.swift:53:14:53:21 | ... .box [x] | semmle.label | ... .box [x] | +| implicit-self.swift:53:14:53:23 | ... .x | semmle.label | ... .x | +| implicit-self.swift:58:9:58:12 | [post] self [box, x] | semmle.label | [post] self [box, x] | +| implicit-self.swift:58:9:58:16 | [post] ... .box [x] | semmle.label | [post] ... .box [x] | +| implicit-self.swift:58:9:58:18 | ... .x | semmle.label | ... .x | +| implicit-self.swift:58:22:58:35 | source(...) | semmle.label | source(...) | +| implicit-self.swift:59:14:59:16 | box [x] | semmle.label | box [x] | +| implicit-self.swift:59:14:59:18 | ... .x | semmle.label | ... .x | +| implicit-self.swift:64:9:64:9 | [incoming] x | semmle.label | [incoming] x | +| implicit-self.swift:64:24:64:37 | source(...) | semmle.label | source(...) | +| implicit-self.swift:65:14:65:14 | x | semmle.label | x | +| implicit-self.swift:66:14:66:17 | self [x] | semmle.label | self [x] | +| implicit-self.swift:66:14:66:19 | ... .x | semmle.label | ... .x | +| implicit-self.swift:71:9:71:12 | [post] self [x] | semmle.label | [post] self [x] | +| implicit-self.swift:71:9:71:14 | [incoming] ... .x | semmle.label | [incoming] ... .x | +| implicit-self.swift:71:29:71:43 | source(...) | semmle.label | source(...) | +| implicit-self.swift:72:14:72:14 | x | semmle.label | x | +| implicit-self.swift:73:14:73:17 | self [x] | semmle.label | self [x] | +| implicit-self.swift:73:14:73:19 | ... .x | semmle.label | ... .x | +| implicit-self.swift:78:9:78:9 | [incoming] x | semmle.label | [incoming] x | +| implicit-self.swift:78:24:78:38 | source(...) | semmle.label | source(...) | +| implicit-self.swift:79:14:79:14 | x | semmle.label | x | +| implicit-self.swift:80:14:80:17 | self [x] | semmle.label | self [x] | +| implicit-self.swift:80:14:80:19 | ... .x | semmle.label | ... .x | +| implicit-self.swift:85:9:85:12 | [post] self [x] | semmle.label | [post] self [x] | +| implicit-self.swift:85:9:85:14 | [incoming] ... .x | semmle.label | [incoming] ... .x | +| implicit-self.swift:85:29:85:43 | source(...) | semmle.label | source(...) | +| implicit-self.swift:86:14:86:14 | x | semmle.label | x | +| implicit-self.swift:87:14:87:17 | self [x] | semmle.label | self [x] | +| implicit-self.swift:87:14:87:19 | ... .x | semmle.label | ... .x | +| test.swift:9:10:9:21 | source(...) | semmle.label | source(...) | +| test.swift:17:10:17:23 | source(...) | semmle.label | source(...) | +| test.swift:17:10:17:32 | ... + ... | semmle.label | ... + ... | +| test.swift:18:10:18:32 | ... + ... | semmle.label | ... + ... | +| test.swift:18:19:18:32 | source(...) | semmle.label | source(...) | +| test.swift:20:10:20:33 | StringInterpolationExpr | semmle.label | StringInterpolationExpr | +| test.swift:20:13:20:26 | source(...) | semmle.label | source(...) | +| test.swift:21:10:21:33 | StringInterpolationExpr | semmle.label | StringInterpolationExpr | +| test.swift:21:18:21:31 | source(...) | semmle.label | source(...) | +| test.swift:22:10:22:38 | StringInterpolationExpr | semmle.label | StringInterpolationExpr | +| test.swift:22:18:22:31 | source(...) | semmle.label | source(...) | +| test.swift:27:10:27:33 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:27:10:27:35 | ... .0 | semmle.label | ... .0 | +| test.swift:27:11:27:25 | source(...) | semmle.label | source(...) | +| test.swift:30:10:30:33 | TupleExpr [1] | semmle.label | TupleExpr [1] | +| test.swift:30:10:30:35 | ... .1 | semmle.label | ... .1 | +| test.swift:30:19:30:32 | source(...) | semmle.label | source(...) | +| test.swift:34:9:34:9 | a | semmle.label | a | +| test.swift:34:13:34:26 | source(...) | semmle.label | source(...) | +| test.swift:35:10:35:10 | a | semmle.label | a | +| test.swift:39:9:39:14 | TupleExpr [0] | semmle.label | TupleExpr [0] | | test.swift:39:10:39:10 | a | semmle.label | a | -| test.swift:46:5:46:9 | [post] tuple [0] | semmle.label | [post] tuple [0] | -| test.swift:46:5:46:11 | ... .0 | semmle.label | ... .0 | -| test.swift:46:15:46:28 | source(...) | semmle.label | source(...) | -| test.swift:47:10:47:14 | tuple [0] | semmle.label | tuple [0] | -| test.swift:47:10:47:16 | ... .0 | semmle.label | ... .0 | -| test.swift:53:5:53:14 | [post] deep_tuple [1, 0] | semmle.label | [post] deep_tuple [1, 0] | -| test.swift:53:5:53:16 | [post] ... .1 [0] | semmle.label | [post] ... .1 [0] | -| test.swift:53:5:53:18 | ... .0 | semmle.label | ... .0 | -| test.swift:53:22:53:35 | source(...) | semmle.label | source(...) | -| test.swift:58:10:58:19 | deep_tuple [1, 0] | semmle.label | deep_tuple [1, 0] | -| test.swift:58:10:58:21 | ... .1 [0] | semmle.label | ... .1 [0] | -| test.swift:58:10:58:23 | ... .0 | semmle.label | ... .0 | -| test.swift:64:5:64:16 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:64:6:64:10 | [post] tuple [1] | semmle.label | [post] tuple [1] | -| test.swift:64:6:64:12 | ... .1 | semmle.label | ... .1 | -| test.swift:64:20:64:51 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:64:21:64:35 | source(...) | semmle.label | source(...) | -| test.swift:66:10:66:14 | tuple [1] | semmle.label | tuple [1] | -| test.swift:66:10:66:16 | ... .1 | semmle.label | ... .1 | -| test.swift:74:5:74:9 | [post] tuple [0] | semmle.label | [post] tuple [0] | -| test.swift:74:5:74:11 | ... .0 | semmle.label | ... .0 | -| test.swift:74:15:74:29 | source(...) | semmle.label | source(...) | -| test.swift:75:10:75:14 | tuple [0] | semmle.label | tuple [0] | -| test.swift:75:10:75:16 | ... .0 | semmle.label | ... .0 | -| test.swift:86:9:86:9 | x | semmle.label | x | -| test.swift:86:13:86:27 | source(...) | semmle.label | source(...) | -| test.swift:90:10:90:10 | x | semmle.label | x | -| test.swift:94:9:94:9 | y | semmle.label | y | -| test.swift:94:13:94:27 | source(...) | semmle.label | source(...) | -| test.swift:96:10:96:10 | y | semmle.label | y | -| test.swift:99:14:99:14 | x | semmle.label | x | -| test.swift:100:14:100:14 | y | semmle.label | y | -| test.swift:107:9:107:13 | [post] tuple [0] | semmle.label | [post] tuple [0] | -| test.swift:107:9:107:15 | ... .0 | semmle.label | ... .0 | -| test.swift:107:19:107:33 | source(...) | semmle.label | source(...) | -| test.swift:112:10:112:14 | tuple [0] | semmle.label | tuple [0] | -| test.swift:112:10:112:16 | ... .0 | semmle.label | ... .0 | -| test.swift:117:9:117:13 | tuple [0] | semmle.label | tuple [0] | -| test.swift:117:9:117:13 | tuple [1] | semmle.label | tuple [1] | -| test.swift:117:17:117:50 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:117:17:117:50 | TupleExpr [1] | semmle.label | TupleExpr [1] | -| test.swift:117:18:117:33 | source(...) | semmle.label | source(...) | -| test.swift:117:35:117:49 | source(...) | semmle.label | source(...) | -| test.swift:120:9:120:13 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:120:9:120:13 | TupleExpr [1] | semmle.label | TupleExpr [1] | -| test.swift:120:10:120:10 | a | semmle.label | a | -| test.swift:120:12:120:12 | b | semmle.label | b | -| test.swift:120:17:120:21 | tuple [0] | semmle.label | tuple [0] | -| test.swift:120:17:120:21 | tuple [1] | semmle.label | tuple [1] | -| test.swift:125:10:125:10 | a | semmle.label | a | -| test.swift:126:10:126:10 | b | semmle.label | b | -| test.swift:131:5:131:5 | a | semmle.label | a | -| test.swift:131:19:131:33 | source(...) | semmle.label | source(...) | -| test.swift:132:10:132:10 | a | semmle.label | a | -| test.swift:137:5:137:5 | [incoming] a | semmle.label | [incoming] a | -| test.swift:137:10:137:24 | source(...) | semmle.label | source(...) | -| test.swift:138:10:138:10 | a | semmle.label | a | -| test.swift:143:5:143:5 | [incoming] a | semmle.label | [incoming] a | -| test.swift:143:20:143:34 | source(...) | semmle.label | source(...) | -| test.swift:144:10:144:10 | a | semmle.label | a | -| test.swift:149:5:149:5 | [post] a [0] | semmle.label | [post] a [0] | -| test.swift:149:5:149:7 | ... .0 | semmle.label | ... .0 | -| test.swift:149:23:149:37 | source(...) | semmle.label | source(...) | -| test.swift:150:10:150:10 | a [0] | semmle.label | a [0] | -| test.swift:150:10:150:12 | ... .0 | semmle.label | ... .0 | -| test.swift:156:5:156:12 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:156:6:156:6 | [post] a [0] | semmle.label | [post] a [0] | -| test.swift:156:6:156:8 | ... .0 | semmle.label | ... .0 | -| test.swift:156:16:156:61 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:156:17:156:43 | ... + ... | semmle.label | ... + ... | -| test.swift:156:29:156:43 | source(...) | semmle.label | source(...) | -| test.swift:157:10:157:10 | a [0] | semmle.label | a [0] | -| test.swift:157:10:157:12 | ... .0 | semmle.label | ... .0 | -| test.swift:164:5:164:10 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:164:5:164:10 | TupleExpr [1] | semmle.label | TupleExpr [1] | -| test.swift:164:6:164:6 | a | semmle.label | a | -| test.swift:164:9:164:9 | b | semmle.label | b | -| test.swift:164:14:164:67 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:164:14:164:67 | TupleExpr [1] | semmle.label | TupleExpr [1] | -| test.swift:164:15:164:39 | ... + ... | semmle.label | ... + ... | -| test.swift:164:25:164:39 | source(...) | semmle.label | source(...) | -| test.swift:164:42:164:66 | ... + ... | semmle.label | ... + ... | -| test.swift:164:52:164:66 | source(...) | semmle.label | source(...) | -| test.swift:165:10:165:10 | a | semmle.label | a | -| test.swift:166:10:166:10 | b | semmle.label | b | +| test.swift:39:18:39:41 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:39:19:39:33 | source(...) | semmle.label | source(...) | +| test.swift:40:10:40:10 | a | semmle.label | a | +| test.swift:43:9:43:14 | TupleExpr [1] | semmle.label | TupleExpr [1] | +| test.swift:43:13:43:13 | d | semmle.label | d | +| test.swift:43:18:43:41 | TupleExpr [1] | semmle.label | TupleExpr [1] | +| test.swift:43:27:43:40 | source(...) | semmle.label | source(...) | +| test.swift:45:10:45:10 | d | semmle.label | d | +| test.swift:49:9:49:9 | a | semmle.label | a | +| test.swift:49:13:49:26 | source(...) | semmle.label | source(...) | +| test.swift:50:10:50:10 | a | semmle.label | a | +| test.swift:57:5:57:9 | [post] tuple [0] | semmle.label | [post] tuple [0] | +| test.swift:57:5:57:11 | ... .0 | semmle.label | ... .0 | +| test.swift:57:15:57:28 | source(...) | semmle.label | source(...) | +| test.swift:58:10:58:14 | tuple [0] | semmle.label | tuple [0] | +| test.swift:58:10:58:16 | ... .0 | semmle.label | ... .0 | +| test.swift:64:5:64:14 | [post] deep_tuple [1, 0] | semmle.label | [post] deep_tuple [1, 0] | +| test.swift:64:5:64:16 | [post] ... .1 [0] | semmle.label | [post] ... .1 [0] | +| test.swift:64:5:64:18 | ... .0 | semmle.label | ... .0 | +| test.swift:64:22:64:35 | source(...) | semmle.label | source(...) | +| test.swift:69:10:69:19 | deep_tuple [1, 0] | semmle.label | deep_tuple [1, 0] | +| test.swift:69:10:69:21 | ... .1 [0] | semmle.label | ... .1 [0] | +| test.swift:69:10:69:23 | ... .0 | semmle.label | ... .0 | +| test.swift:75:5:75:16 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:75:6:75:10 | [post] tuple [1] | semmle.label | [post] tuple [1] | +| test.swift:75:6:75:12 | ... .1 | semmle.label | ... .1 | +| test.swift:75:20:75:51 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:75:21:75:35 | source(...) | semmle.label | source(...) | +| test.swift:77:10:77:14 | tuple [1] | semmle.label | tuple [1] | +| test.swift:77:10:77:16 | ... .1 | semmle.label | ... .1 | +| test.swift:85:5:85:9 | [post] tuple [0] | semmle.label | [post] tuple [0] | +| test.swift:85:5:85:11 | ... .0 | semmle.label | ... .0 | +| test.swift:85:15:85:29 | source(...) | semmle.label | source(...) | +| test.swift:86:10:86:14 | tuple [0] | semmle.label | tuple [0] | +| test.swift:86:10:86:16 | ... .0 | semmle.label | ... .0 | +| test.swift:97:9:97:9 | x | semmle.label | x | +| test.swift:97:13:97:27 | source(...) | semmle.label | source(...) | +| test.swift:101:10:101:10 | x | semmle.label | x | +| test.swift:105:9:105:9 | y | semmle.label | y | +| test.swift:105:13:105:27 | source(...) | semmle.label | source(...) | +| test.swift:107:10:107:10 | y | semmle.label | y | +| test.swift:110:14:110:14 | x | semmle.label | x | +| test.swift:111:14:111:14 | y | semmle.label | y | +| test.swift:118:9:118:13 | [post] tuple [0] | semmle.label | [post] tuple [0] | +| test.swift:118:9:118:15 | ... .0 | semmle.label | ... .0 | +| test.swift:118:19:118:33 | source(...) | semmle.label | source(...) | +| test.swift:123:10:123:14 | tuple [0] | semmle.label | tuple [0] | +| test.swift:123:10:123:16 | ... .0 | semmle.label | ... .0 | +| test.swift:128:9:128:13 | tuple [0] | semmle.label | tuple [0] | +| test.swift:128:9:128:13 | tuple [1] | semmle.label | tuple [1] | +| test.swift:128:17:128:50 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:128:17:128:50 | TupleExpr [1] | semmle.label | TupleExpr [1] | +| test.swift:128:18:128:33 | source(...) | semmle.label | source(...) | +| test.swift:128:35:128:49 | source(...) | semmle.label | source(...) | +| test.swift:131:9:131:14 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:131:9:131:14 | TupleExpr [1] | semmle.label | TupleExpr [1] | +| test.swift:131:10:131:10 | a | semmle.label | a | +| test.swift:131:13:131:13 | b | semmle.label | b | +| test.swift:131:18:131:22 | tuple [0] | semmle.label | tuple [0] | +| test.swift:131:18:131:22 | tuple [1] | semmle.label | tuple [1] | +| test.swift:136:10:136:10 | a | semmle.label | a | +| test.swift:137:10:137:10 | b | semmle.label | b | +| test.swift:142:5:142:5 | a | semmle.label | a | +| test.swift:142:19:142:33 | source(...) | semmle.label | source(...) | +| test.swift:143:10:143:10 | a | semmle.label | a | +| test.swift:148:5:148:5 | [incoming] a | semmle.label | [incoming] a | +| test.swift:148:10:148:24 | source(...) | semmle.label | source(...) | +| test.swift:149:10:149:10 | a | semmle.label | a | +| test.swift:154:5:154:5 | [incoming] a | semmle.label | [incoming] a | +| test.swift:154:20:154:34 | source(...) | semmle.label | source(...) | +| test.swift:155:10:155:10 | a | semmle.label | a | +| test.swift:160:5:160:5 | [post] a [0] | semmle.label | [post] a [0] | +| test.swift:160:5:160:7 | ... .0 | semmle.label | ... .0 | +| test.swift:160:23:160:37 | source(...) | semmle.label | source(...) | +| test.swift:161:10:161:10 | a [0] | semmle.label | a [0] | +| test.swift:161:10:161:12 | ... .0 | semmle.label | ... .0 | +| test.swift:167:5:167:12 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:167:6:167:6 | [post] a [0] | semmle.label | [post] a [0] | +| test.swift:167:6:167:8 | ... .0 | semmle.label | ... .0 | +| test.swift:167:16:167:61 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:167:17:167:43 | ... + ... | semmle.label | ... + ... | +| test.swift:167:29:167:43 | source(...) | semmle.label | source(...) | +| test.swift:168:10:168:10 | a [0] | semmle.label | a [0] | +| test.swift:168:10:168:12 | ... .0 | semmle.label | ... .0 | +| test.swift:175:5:175:10 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:175:5:175:10 | TupleExpr [1] | semmle.label | TupleExpr [1] | +| test.swift:175:6:175:6 | a | semmle.label | a | +| test.swift:175:9:175:9 | b | semmle.label | b | +| test.swift:175:14:175:67 | TupleExpr [0] | semmle.label | TupleExpr [0] | +| test.swift:175:14:175:67 | TupleExpr [1] | semmle.label | TupleExpr [1] | +| test.swift:175:15:175:39 | ... + ... | semmle.label | ... + ... | +| test.swift:175:25:175:39 | source(...) | semmle.label | source(...) | +| test.swift:175:42:175:66 | ... + ... | semmle.label | ... + ... | +| test.swift:175:52:175:66 | source(...) | semmle.label | source(...) | +| test.swift:176:10:176:10 | a | semmle.label | a | +| test.swift:177:10:177:10 | b | semmle.label | b | subpaths +| calls.swift:31:17:31:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:31:10:31:31 | target(...) | +| calls.swift:32:17:32:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:32:10:32:31 | target(...) | testFailures #select -| implicit-self.swift:12:14:12:19 | ... .x | implicit-self.swift:11:18:11:31 | source(...) | implicit-self.swift:12:14:12:19 | ... .x | $@ | implicit-self.swift:11:18:11:31 | source(...) | source(...) | -| implicit-self.swift:18:14:18:14 | x | implicit-self.swift:17:13:17:26 | source(...) | implicit-self.swift:18:14:18:14 | x | $@ | implicit-self.swift:17:13:17:26 | source(...) | source(...) | -| implicit-self.swift:24:14:24:19 | ... .x | implicit-self.swift:23:13:23:26 | source(...) | implicit-self.swift:24:14:24:19 | ... .x | $@ | implicit-self.swift:23:13:23:26 | source(...) | source(...) | -| implicit-self.swift:30:14:30:14 | x | implicit-self.swift:29:18:29:31 | source(...) | implicit-self.swift:30:14:30:14 | x | $@ | implicit-self.swift:29:18:29:31 | source(...) | source(...) | -| implicit-self.swift:36:14:36:23 | ... .x | implicit-self.swift:35:22:35:35 | source(...) | implicit-self.swift:36:14:36:23 | ... .x | $@ | implicit-self.swift:35:22:35:35 | source(...) | source(...) | -| implicit-self.swift:42:14:42:18 | ... .x | implicit-self.swift:41:17:41:30 | source(...) | implicit-self.swift:42:14:42:18 | ... .x | $@ | implicit-self.swift:41:17:41:30 | source(...) | source(...) | -| implicit-self.swift:48:14:48:23 | ... .x | implicit-self.swift:47:17:47:30 | source(...) | implicit-self.swift:48:14:48:23 | ... .x | $@ | implicit-self.swift:47:17:47:30 | source(...) | source(...) | -| implicit-self.swift:54:14:54:18 | ... .x | implicit-self.swift:53:22:53:35 | source(...) | implicit-self.swift:54:14:54:18 | ... .x | $@ | implicit-self.swift:53:22:53:35 | source(...) | source(...) | -| implicit-self.swift:60:14:60:14 | x | implicit-self.swift:59:24:59:37 | source(...) | implicit-self.swift:60:14:60:14 | x | $@ | implicit-self.swift:59:24:59:37 | source(...) | source(...) | -| implicit-self.swift:61:14:61:19 | ... .x | implicit-self.swift:59:24:59:37 | source(...) | implicit-self.swift:61:14:61:19 | ... .x | $@ | implicit-self.swift:59:24:59:37 | source(...) | source(...) | -| implicit-self.swift:67:14:67:14 | x | implicit-self.swift:66:29:66:43 | source(...) | implicit-self.swift:67:14:67:14 | x | $@ | implicit-self.swift:66:29:66:43 | source(...) | source(...) | -| implicit-self.swift:68:14:68:19 | ... .x | implicit-self.swift:66:29:66:43 | source(...) | implicit-self.swift:68:14:68:19 | ... .x | $@ | implicit-self.swift:66:29:66:43 | source(...) | source(...) | -| implicit-self.swift:74:14:74:14 | x | implicit-self.swift:73:24:73:38 | source(...) | implicit-self.swift:74:14:74:14 | x | $@ | implicit-self.swift:73:24:73:38 | source(...) | source(...) | -| implicit-self.swift:75:14:75:19 | ... .x | implicit-self.swift:73:24:73:38 | source(...) | implicit-self.swift:75:14:75:19 | ... .x | $@ | implicit-self.swift:73:24:73:38 | source(...) | source(...) | -| implicit-self.swift:81:14:81:14 | x | implicit-self.swift:80:29:80:43 | source(...) | implicit-self.swift:81:14:81:14 | x | $@ | implicit-self.swift:80:29:80:43 | source(...) | source(...) | -| implicit-self.swift:82:14:82:19 | ... .x | implicit-self.swift:80:29:80:43 | source(...) | implicit-self.swift:82:14:82:19 | ... .x | $@ | implicit-self.swift:80:29:80:43 | source(...) | source(...) | -| test.swift:2:10:2:21 | source(...) | test.swift:2:10:2:21 | source(...) | test.swift:2:10:2:21 | source(...) | $@ | test.swift:2:10:2:21 | source(...) | source(...) | -| test.swift:6:10:6:32 | ... + ... | test.swift:6:10:6:23 | source(...) | test.swift:6:10:6:32 | ... + ... | $@ | test.swift:6:10:6:23 | source(...) | source(...) | -| test.swift:7:10:7:32 | ... + ... | test.swift:7:19:7:32 | source(...) | test.swift:7:10:7:32 | ... + ... | $@ | test.swift:7:19:7:32 | source(...) | source(...) | -| test.swift:9:10:9:33 | StringInterpolationExpr | test.swift:9:13:9:26 | source(...) | test.swift:9:10:9:33 | StringInterpolationExpr | $@ | test.swift:9:13:9:26 | source(...) | source(...) | -| test.swift:10:10:10:33 | StringInterpolationExpr | test.swift:10:18:10:31 | source(...) | test.swift:10:10:10:33 | StringInterpolationExpr | $@ | test.swift:10:18:10:31 | source(...) | source(...) | -| test.swift:11:10:11:38 | StringInterpolationExpr | test.swift:11:18:11:31 | source(...) | test.swift:11:10:11:38 | StringInterpolationExpr | $@ | test.swift:11:18:11:31 | source(...) | source(...) | -| test.swift:16:10:16:35 | ... .0 | test.swift:16:11:16:25 | source(...) | test.swift:16:10:16:35 | ... .0 | $@ | test.swift:16:11:16:25 | source(...) | source(...) | -| test.swift:19:10:19:35 | ... .1 | test.swift:19:19:19:32 | source(...) | test.swift:19:10:19:35 | ... .1 | $@ | test.swift:19:19:19:32 | source(...) | source(...) | -| test.swift:24:10:24:10 | a | test.swift:23:13:23:26 | source(...) | test.swift:24:10:24:10 | a | $@ | test.swift:23:13:23:26 | source(...) | source(...) | -| test.swift:29:10:29:10 | a | test.swift:28:19:28:33 | source(...) | test.swift:29:10:29:10 | a | $@ | test.swift:28:19:28:33 | source(...) | source(...) | -| test.swift:34:10:34:10 | d | test.swift:32:27:32:40 | source(...) | test.swift:34:10:34:10 | d | $@ | test.swift:32:27:32:40 | source(...) | source(...) | -| test.swift:39:10:39:10 | a | test.swift:38:13:38:26 | source(...) | test.swift:39:10:39:10 | a | $@ | test.swift:38:13:38:26 | source(...) | source(...) | -| test.swift:47:10:47:16 | ... .0 | test.swift:46:15:46:28 | source(...) | test.swift:47:10:47:16 | ... .0 | $@ | test.swift:46:15:46:28 | source(...) | source(...) | -| test.swift:58:10:58:23 | ... .0 | test.swift:53:22:53:35 | source(...) | test.swift:58:10:58:23 | ... .0 | $@ | test.swift:53:22:53:35 | source(...) | source(...) | -| test.swift:66:10:66:16 | ... .1 | test.swift:64:21:64:35 | source(...) | test.swift:66:10:66:16 | ... .1 | $@ | test.swift:64:21:64:35 | source(...) | source(...) | -| test.swift:75:10:75:16 | ... .0 | test.swift:74:15:74:29 | source(...) | test.swift:75:10:75:16 | ... .0 | $@ | test.swift:74:15:74:29 | source(...) | source(...) | -| test.swift:90:10:90:10 | x | test.swift:86:13:86:27 | source(...) | test.swift:90:10:90:10 | x | $@ | test.swift:86:13:86:27 | source(...) | source(...) | -| test.swift:96:10:96:10 | y | test.swift:94:13:94:27 | source(...) | test.swift:96:10:96:10 | y | $@ | test.swift:94:13:94:27 | source(...) | source(...) | -| test.swift:99:14:99:14 | x | test.swift:86:13:86:27 | source(...) | test.swift:99:14:99:14 | x | $@ | test.swift:86:13:86:27 | source(...) | source(...) | -| test.swift:100:14:100:14 | y | test.swift:94:13:94:27 | source(...) | test.swift:100:14:100:14 | y | $@ | test.swift:94:13:94:27 | source(...) | source(...) | -| test.swift:112:10:112:16 | ... .0 | test.swift:107:19:107:33 | source(...) | test.swift:112:10:112:16 | ... .0 | $@ | test.swift:107:19:107:33 | source(...) | source(...) | -| test.swift:125:10:125:10 | a | test.swift:117:18:117:33 | source(...) | test.swift:125:10:125:10 | a | $@ | test.swift:117:18:117:33 | source(...) | source(...) | -| test.swift:126:10:126:10 | b | test.swift:117:35:117:49 | source(...) | test.swift:126:10:126:10 | b | $@ | test.swift:117:35:117:49 | source(...) | source(...) | -| test.swift:132:10:132:10 | a | test.swift:131:19:131:33 | source(...) | test.swift:132:10:132:10 | a | $@ | test.swift:131:19:131:33 | source(...) | source(...) | -| test.swift:138:10:138:10 | a | test.swift:137:10:137:24 | source(...) | test.swift:138:10:138:10 | a | $@ | test.swift:137:10:137:24 | source(...) | source(...) | -| test.swift:144:10:144:10 | a | test.swift:143:20:143:34 | source(...) | test.swift:144:10:144:10 | a | $@ | test.swift:143:20:143:34 | source(...) | source(...) | -| test.swift:150:10:150:12 | ... .0 | test.swift:149:23:149:37 | source(...) | test.swift:150:10:150:12 | ... .0 | $@ | test.swift:149:23:149:37 | source(...) | source(...) | -| test.swift:157:10:157:12 | ... .0 | test.swift:156:29:156:43 | source(...) | test.swift:157:10:157:12 | ... .0 | $@ | test.swift:156:29:156:43 | source(...) | source(...) | -| test.swift:165:10:165:10 | a | test.swift:164:25:164:39 | source(...) | test.swift:165:10:165:10 | a | $@ | test.swift:164:25:164:39 | source(...) | source(...) | -| test.swift:166:10:166:10 | b | test.swift:164:52:164:66 | source(...) | test.swift:166:10:166:10 | b | $@ | test.swift:164:52:164:66 | source(...) | source(...) | +| calls.swift:8:14:8:14 | x | calls.swift:10:12:10:25 | source(...) | calls.swift:8:14:8:14 | x | $@ | calls.swift:10:12:10:25 | source(...) | source(...) | +| calls.swift:17:10:17:17 | target(...) | calls.swift:15:16:15:29 | source(...) | calls.swift:17:10:17:17 | target(...) | $@ | calls.swift:15:16:15:29 | source(...) | source(...) | +| calls.swift:22:14:22:14 | x | calls.swift:24:12:24:28 | source(...) | calls.swift:22:14:22:14 | x | $@ | calls.swift:24:12:24:28 | source(...) | source(...) | +| calls.swift:31:10:31:31 | target(...) | calls.swift:31:17:31:30 | source(...) | calls.swift:31:10:31:31 | target(...) | $@ | calls.swift:31:17:31:30 | source(...) | source(...) | +| calls.swift:32:10:32:31 | target(...) | calls.swift:32:17:32:30 | source(...) | calls.swift:32:10:32:31 | target(...) | $@ | calls.swift:32:17:32:30 | source(...) | source(...) | +| calls.swift:38:14:38:14 | x | calls.swift:40:13:40:32 | source(...) | calls.swift:38:14:38:14 | x | $@ | calls.swift:40:13:40:32 | source(...) | source(...) | +| calls.swift:43:14:43:17 | name | calls.swift:45:13:45:32 | source(...) | calls.swift:43:14:43:17 | name | $@ | calls.swift:45:13:45:32 | source(...) | source(...) | +| calls.swift:50:14:50:14 | x | calls.swift:53:12:53:26 | source(...) | calls.swift:50:14:50:14 | x | $@ | calls.swift:53:12:53:26 | source(...) | source(...) | +| calls.swift:51:14:51:14 | y | calls.swift:53:28:53:41 | source(...) | calls.swift:51:14:51:14 | y | $@ | calls.swift:53:28:53:41 | source(...) | source(...) | +| calls.swift:67:10:67:16 | ... .field | calls.swift:62:19:62:32 | source(...) | calls.swift:67:10:67:16 | ... .field | $@ | calls.swift:62:19:62:32 | source(...) | source(...) | +| calls.swift:81:18:81:22 | field | calls.swift:75:21:75:34 | source(...) | calls.swift:81:18:81:22 | field | $@ | calls.swift:75:21:75:34 | source(...) | source(...) | +| calls.swift:87:18:87:27 | ... .field | calls.swift:75:21:75:34 | source(...) | calls.swift:87:18:87:27 | ... .field | $@ | calls.swift:75:21:75:34 | source(...) | source(...) | +| calls.swift:105:18:105:22 | field | calls.swift:75:21:75:34 | source(...) | calls.swift:105:18:105:22 | field | $@ | calls.swift:75:21:75:34 | source(...) | source(...) | +| calls.swift:111:18:111:27 | ... .field | calls.swift:75:21:75:34 | source(...) | calls.swift:111:18:111:27 | ... .field | $@ | calls.swift:75:21:75:34 | source(...) | source(...) | +| implicit-self.swift:17:14:17:19 | ... .x | implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:17:14:17:19 | ... .x | $@ | implicit-self.swift:16:18:16:31 | source(...) | source(...) | +| implicit-self.swift:23:14:23:14 | x | implicit-self.swift:22:13:22:26 | source(...) | implicit-self.swift:23:14:23:14 | x | $@ | implicit-self.swift:22:13:22:26 | source(...) | source(...) | +| implicit-self.swift:29:14:29:19 | ... .x | implicit-self.swift:28:13:28:26 | source(...) | implicit-self.swift:29:14:29:19 | ... .x | $@ | implicit-self.swift:28:13:28:26 | source(...) | source(...) | +| implicit-self.swift:35:14:35:14 | x | implicit-self.swift:34:18:34:31 | source(...) | implicit-self.swift:35:14:35:14 | x | $@ | implicit-self.swift:34:18:34:31 | source(...) | source(...) | +| implicit-self.swift:41:14:41:23 | ... .x | implicit-self.swift:40:22:40:35 | source(...) | implicit-self.swift:41:14:41:23 | ... .x | $@ | implicit-self.swift:40:22:40:35 | source(...) | source(...) | +| implicit-self.swift:47:14:47:18 | ... .x | implicit-self.swift:46:17:46:30 | source(...) | implicit-self.swift:47:14:47:18 | ... .x | $@ | implicit-self.swift:46:17:46:30 | source(...) | source(...) | +| implicit-self.swift:53:14:53:23 | ... .x | implicit-self.swift:52:17:52:30 | source(...) | implicit-self.swift:53:14:53:23 | ... .x | $@ | implicit-self.swift:52:17:52:30 | source(...) | source(...) | +| implicit-self.swift:59:14:59:18 | ... .x | implicit-self.swift:58:22:58:35 | source(...) | implicit-self.swift:59:14:59:18 | ... .x | $@ | implicit-self.swift:58:22:58:35 | source(...) | source(...) | +| implicit-self.swift:65:14:65:14 | x | implicit-self.swift:64:24:64:37 | source(...) | implicit-self.swift:65:14:65:14 | x | $@ | implicit-self.swift:64:24:64:37 | source(...) | source(...) | +| implicit-self.swift:66:14:66:19 | ... .x | implicit-self.swift:64:24:64:37 | source(...) | implicit-self.swift:66:14:66:19 | ... .x | $@ | implicit-self.swift:64:24:64:37 | source(...) | source(...) | +| implicit-self.swift:72:14:72:14 | x | implicit-self.swift:71:29:71:43 | source(...) | implicit-self.swift:72:14:72:14 | x | $@ | implicit-self.swift:71:29:71:43 | source(...) | source(...) | +| implicit-self.swift:73:14:73:19 | ... .x | implicit-self.swift:71:29:71:43 | source(...) | implicit-self.swift:73:14:73:19 | ... .x | $@ | implicit-self.swift:71:29:71:43 | source(...) | source(...) | +| implicit-self.swift:79:14:79:14 | x | implicit-self.swift:78:24:78:38 | source(...) | implicit-self.swift:79:14:79:14 | x | $@ | implicit-self.swift:78:24:78:38 | source(...) | source(...) | +| implicit-self.swift:80:14:80:19 | ... .x | implicit-self.swift:78:24:78:38 | source(...) | implicit-self.swift:80:14:80:19 | ... .x | $@ | implicit-self.swift:78:24:78:38 | source(...) | source(...) | +| implicit-self.swift:86:14:86:14 | x | implicit-self.swift:85:29:85:43 | source(...) | implicit-self.swift:86:14:86:14 | x | $@ | implicit-self.swift:85:29:85:43 | source(...) | source(...) | +| implicit-self.swift:87:14:87:19 | ... .x | implicit-self.swift:85:29:85:43 | source(...) | implicit-self.swift:87:14:87:19 | ... .x | $@ | implicit-self.swift:85:29:85:43 | source(...) | source(...) | +| test.swift:9:10:9:21 | source(...) | test.swift:9:10:9:21 | source(...) | test.swift:9:10:9:21 | source(...) | $@ | test.swift:9:10:9:21 | source(...) | source(...) | +| test.swift:17:10:17:32 | ... + ... | test.swift:17:10:17:23 | source(...) | test.swift:17:10:17:32 | ... + ... | $@ | test.swift:17:10:17:23 | source(...) | source(...) | +| test.swift:18:10:18:32 | ... + ... | test.swift:18:19:18:32 | source(...) | test.swift:18:10:18:32 | ... + ... | $@ | test.swift:18:19:18:32 | source(...) | source(...) | +| test.swift:20:10:20:33 | StringInterpolationExpr | test.swift:20:13:20:26 | source(...) | test.swift:20:10:20:33 | StringInterpolationExpr | $@ | test.swift:20:13:20:26 | source(...) | source(...) | +| test.swift:21:10:21:33 | StringInterpolationExpr | test.swift:21:18:21:31 | source(...) | test.swift:21:10:21:33 | StringInterpolationExpr | $@ | test.swift:21:18:21:31 | source(...) | source(...) | +| test.swift:22:10:22:38 | StringInterpolationExpr | test.swift:22:18:22:31 | source(...) | test.swift:22:10:22:38 | StringInterpolationExpr | $@ | test.swift:22:18:22:31 | source(...) | source(...) | +| test.swift:27:10:27:35 | ... .0 | test.swift:27:11:27:25 | source(...) | test.swift:27:10:27:35 | ... .0 | $@ | test.swift:27:11:27:25 | source(...) | source(...) | +| test.swift:30:10:30:35 | ... .1 | test.swift:30:19:30:32 | source(...) | test.swift:30:10:30:35 | ... .1 | $@ | test.swift:30:19:30:32 | source(...) | source(...) | +| test.swift:35:10:35:10 | a | test.swift:34:13:34:26 | source(...) | test.swift:35:10:35:10 | a | $@ | test.swift:34:13:34:26 | source(...) | source(...) | +| test.swift:40:10:40:10 | a | test.swift:39:19:39:33 | source(...) | test.swift:40:10:40:10 | a | $@ | test.swift:39:19:39:33 | source(...) | source(...) | +| test.swift:45:10:45:10 | d | test.swift:43:27:43:40 | source(...) | test.swift:45:10:45:10 | d | $@ | test.swift:43:27:43:40 | source(...) | source(...) | +| test.swift:50:10:50:10 | a | test.swift:49:13:49:26 | source(...) | test.swift:50:10:50:10 | a | $@ | test.swift:49:13:49:26 | source(...) | source(...) | +| test.swift:58:10:58:16 | ... .0 | test.swift:57:15:57:28 | source(...) | test.swift:58:10:58:16 | ... .0 | $@ | test.swift:57:15:57:28 | source(...) | source(...) | +| test.swift:69:10:69:23 | ... .0 | test.swift:64:22:64:35 | source(...) | test.swift:69:10:69:23 | ... .0 | $@ | test.swift:64:22:64:35 | source(...) | source(...) | +| test.swift:77:10:77:16 | ... .1 | test.swift:75:21:75:35 | source(...) | test.swift:77:10:77:16 | ... .1 | $@ | test.swift:75:21:75:35 | source(...) | source(...) | +| test.swift:86:10:86:16 | ... .0 | test.swift:85:15:85:29 | source(...) | test.swift:86:10:86:16 | ... .0 | $@ | test.swift:85:15:85:29 | source(...) | source(...) | +| test.swift:101:10:101:10 | x | test.swift:97:13:97:27 | source(...) | test.swift:101:10:101:10 | x | $@ | test.swift:97:13:97:27 | source(...) | source(...) | +| test.swift:107:10:107:10 | y | test.swift:105:13:105:27 | source(...) | test.swift:107:10:107:10 | y | $@ | test.swift:105:13:105:27 | source(...) | source(...) | +| test.swift:110:14:110:14 | x | test.swift:97:13:97:27 | source(...) | test.swift:110:14:110:14 | x | $@ | test.swift:97:13:97:27 | source(...) | source(...) | +| test.swift:111:14:111:14 | y | test.swift:105:13:105:27 | source(...) | test.swift:111:14:111:14 | y | $@ | test.swift:105:13:105:27 | source(...) | source(...) | +| test.swift:123:10:123:16 | ... .0 | test.swift:118:19:118:33 | source(...) | test.swift:123:10:123:16 | ... .0 | $@ | test.swift:118:19:118:33 | source(...) | source(...) | +| test.swift:136:10:136:10 | a | test.swift:128:18:128:33 | source(...) | test.swift:136:10:136:10 | a | $@ | test.swift:128:18:128:33 | source(...) | source(...) | +| test.swift:137:10:137:10 | b | test.swift:128:35:128:49 | source(...) | test.swift:137:10:137:10 | b | $@ | test.swift:128:35:128:49 | source(...) | source(...) | +| test.swift:143:10:143:10 | a | test.swift:142:19:142:33 | source(...) | test.swift:143:10:143:10 | a | $@ | test.swift:142:19:142:33 | source(...) | source(...) | +| test.swift:149:10:149:10 | a | test.swift:148:10:148:24 | source(...) | test.swift:149:10:149:10 | a | $@ | test.swift:148:10:148:24 | source(...) | source(...) | +| test.swift:155:10:155:10 | a | test.swift:154:20:154:34 | source(...) | test.swift:155:10:155:10 | a | $@ | test.swift:154:20:154:34 | source(...) | source(...) | +| test.swift:161:10:161:12 | ... .0 | test.swift:160:23:160:37 | source(...) | test.swift:161:10:161:12 | ... .0 | $@ | test.swift:160:23:160:37 | source(...) | source(...) | +| test.swift:168:10:168:12 | ... .0 | test.swift:167:29:167:43 | source(...) | test.swift:168:10:168:12 | ... .0 | $@ | test.swift:167:29:167:43 | source(...) | source(...) | +| test.swift:176:10:176:10 | a | test.swift:175:25:175:39 | source(...) | test.swift:176:10:176:10 | a | $@ | test.swift:175:25:175:39 | source(...) | source(...) | +| test.swift:177:10:177:10 | b | test.swift:175:52:175:66 | source(...) | test.swift:177:10:177:10 | b | $@ | test.swift:175:52:175:66 | source(...) | source(...) | diff --git a/unified/ql/test/library-tests/dataflow/test.swift b/unified/ql/test/library-tests/dataflow/test.swift index 988bcfe03f52..a7fa42ee6100 100644 --- a/unified/ql/test/library-tests/dataflow/test.swift +++ b/unified/ql/test/library-tests/dataflow/test.swift @@ -1,167 +1,178 @@ +func source(_ s: String) -> String { return s } + +@discardableResult +func sink(_ s: Any) -> String { return "" } + +func foo() -> Bool { return 5 > 5 } + func t1() { - sink(source("t1")); // $ hasValueFlow=t1 + sink(source("t1")) // $ hasValueFlow=t1 +} + +extension DefaultStringInterpolation { + mutating func appendInterpolation(escape value: String) {} } func t2() { - sink(source("t2.1") + "blah"); // $ hasTaintFlow=t2.1 - sink("blah" + source("t2.2")); // $ hasTaintFlow=t2.2 + sink(source("t2.1") + "blah") // $ hasTaintFlow=t2.1 + sink("blah" + source("t2.2")) // $ hasTaintFlow=t2.2 - sink("\(source("t2.3")) blah"); // $ hasTaintFlow=t2.3 - sink("blah \(source("t2.4"))"); // $ hasTaintFlow=t2.4 - sink("blah \(source("t2.5")) blah"); // $ hasTaintFlow=t2.5 - sink("blah \(escape: source("t2.6")) blah"); // no flow + sink("\(source("t2.3")) blah") // $ hasTaintFlow=t2.3 + sink("blah \(source("t2.4"))") // $ hasTaintFlow=t2.4 + sink("blah \(source("t2.5")) blah") // $ hasTaintFlow=t2.5 + sink("blah \(escape: source("t2.6")) blah") // no flow } func t3() { - sink((source("t3.1"), "safe").0); // $ hasValueFlow=t3.1 - sink((source("t3.2"), "safe").1); // no flow - sink(("safe", source("t3.3")).0); // no flow - sink(("safe", source("t3.4")).1); // $ hasValueFlow=t3.4 + sink((source("t3.1"), "safe").0) // $ hasValueFlow=t3.1 + sink((source("t3.2"), "safe").1) // no flow + sink(("safe", source("t3.3")).0) // no flow + sink(("safe", source("t3.4")).1) // $ hasValueFlow=t3.4 } func t4() { - let a = source("t4.1"); - sink(a); // $ hasValueFlow=t4.1 + let a = source("t4.1") + sink(a) // $ hasValueFlow=t4.1 } func t5() { - let (a, b) = (source("t5.1"), "safe"); - sink(a); // $ hasValueFlow=t5.1 - sink(b); // no flow + let (a, b) = (source("t5.1"), "safe") + sink(a) // $ hasValueFlow=t5.1 + sink(b) // no flow - let (c, d) = ("safe", source("t5.2")); - sink(c); // no flow - sink(d); // $ hasValueFlow=t5.2 + let (c, d) = ("safe", source("t5.2")) + sink(c) // no flow + sink(d) // $ hasValueFlow=t5.2 } func t6() { - var a = source("t6.1"); - sink(a); // $ hasValueFlow=t6.1 - a = "safe"; - sink(a); + var a = source("t6.1") + sink(a) // $ hasValueFlow=t6.1 + a = "safe" + sink(a) } func t7() { var tuple = ("safe", "safe") - tuple.0 = source("t7.1"); - sink(tuple.0); // $ hasValueFlow=t7.1 - sink(tuple.1); // no flow + tuple.0 = source("t7.1") + sink(tuple.0) // $ hasValueFlow=t7.1 + sink(tuple.1) // no flow } func t8() { var deep_tuple = (("safe", "safe"), ("safe", "safe")) - deep_tuple.1.0 = source("t8.1"); - sink(deep_tuple); // no flow - sink(deep_tuple.0); // no flow - sink(deep_tuple.1); // no flow - sink(deep_tuple.0.1); // no flow - sink(deep_tuple.1.0); // $ hasValueFlow=t8.1 - sink(deep_tuple.1.1); // no flow + deep_tuple.1.0 = source("t8.1") + sink(deep_tuple) // no flow + sink(deep_tuple.0) // no flow + sink(deep_tuple.1) // no flow + sink(deep_tuple.0.1) // no flow + sink(deep_tuple.1.0) // $ hasValueFlow=t8.1 + sink(deep_tuple.1.1) // no flow } func t9() { var tuple = ("safe", "safe") - (tuple.1, _) = (source("t9.1"), source("t9.2")); - sink(tuple.0); // no flow - sink(tuple.1); // $ hasValueFlow=t9.1 + (tuple.1, _) = (source("t9.1"), source("t9.2")) + sink(tuple.0) // no flow + sink(tuple.1) // $ hasValueFlow=t9.1 } func t10() { var tuple = ("safe", "safe") - sink(tuple.0); // no flow - sink(tuple.1); // no flow + sink(tuple.0) // no flow + sink(tuple.1) // no flow - tuple.0 = source("t10.1"); - sink(tuple.0); // $ hasValueFlow=t10.1 - sink(tuple.1); // no flow + tuple.0 = source("t10.1") + sink(tuple.0) // $ hasValueFlow=t10.1 + sink(tuple.1) // no flow - tuple = ("safe", "safe"); - sink(tuple.0); // no flow - sink(tuple.1); // no flow + tuple = ("safe", "safe") + sink(tuple.0) // no flow + sink(tuple.1) // no flow } func t11() { - var x = "safe"; - if (foo()) { - x = source("t11.1"); + var x = "safe" + if foo() { + x = source("t11.1") } else { - sink(x); // no flow + sink(x) // no flow } - sink(x); // $ hasValueFlow=t11.1 + sink(x) // $ hasValueFlow=t11.1 - var y = "safe"; - if (foo()) { - y = source("t11.2"); + var y = "safe" + if foo() { + y = source("t11.2") } - sink(y); // $ hasValueFlow=t11.2 + sink(y) // $ hasValueFlow=t11.2 - if (foo()) { - sink(x); // $ hasValueFlow=t11.1 - sink(y); // $ hasValueFlow=t11.2 + if foo() { + sink(x) // $ hasValueFlow=t11.1 + sink(y) // $ hasValueFlow=t11.2 } } func t12() { - var tuple = ("safe", "safe"); - if (foo()) { - tuple.0 = source("t12.1"); + var tuple = ("safe", "safe") + if foo() { + tuple.0 = source("t12.1") } else { - sink(tuple.0); // no flow - sink(tuple.1); // no flow + sink(tuple.0) // no flow + sink(tuple.1) // no flow } - sink(tuple.0); // $ hasValueFlow=t12.1 - sink(tuple.1); // no flow + sink(tuple.0) // $ hasValueFlow=t12.1 + sink(tuple.1) // no flow } func t13() { - var tuple = (source("t13.1"), source("t13.2")); - var (a,b) = ("safe", "safe") - if (foo()) { - (a,b) = tuple + let tuple = (source("t13.1"), source("t13.2")) + var (a, b) = ("safe", "safe") + if foo() { + (a, b) = tuple } else { - sink(a); // no flow - sink(b); // no flow + sink(a) // no flow + sink(b) // no flow } - sink(a); // $ hasValueFlow=t13.1 - sink(b); // $ hasValueFlow=t13.2 + sink(a) // $ hasValueFlow=t13.1 + sink(b) // $ hasValueFlow=t13.2 } func t14() { - var a = "safe"; - a = sink(a) + source("t14.1"); - sink(a); // $ hasTaintFlow=t14.1 + var a = "safe" + a = sink(a) + source("t14.1") + sink(a) // $ hasTaintFlow=t14.1 } func t15() { - var a = "safe"; - a += source("t15.1"); - sink(a); // $ hasTaintFlow=t15.1 + var a = "safe" + a += source("t15.1") + sink(a) // $ hasTaintFlow=t15.1 } func t16() { - var a = "safe"; - a += sink(a) + source("t16.1"); - sink(a); // $ hasTaintFlow=t16.1 + var a = "safe" + a += sink(a) + source("t16.1") + sink(a) // $ hasTaintFlow=t16.1 } func t17() { - var a = ("safe", "safe"); - a.0 = sink(a.0) + source("t17.1"); - sink(a.0); // $ hasTaintFlow=t17.1 - sink(a.1); // no flow + var a = ("safe", "safe") + a.0 = sink(a.0) + source("t17.1") + sink(a.0) // $ hasTaintFlow=t17.1 + sink(a.1) // no flow } func t18() { - var a = ("safe", "safe"); - (a.0, _) = (sink(a.0) + source("t18.1"), source("t18.2")); - sink(a.0); // $ hasTaintFlow=t18.1 - sink(a.1); // no flow + var a = ("safe", "safe") + (a.0, _) = (sink(a.0) + source("t18.1"), source("t18.2")) + sink(a.0) // $ hasTaintFlow=t18.1 + sink(a.1) // no flow } func t19() { - var a = "safe"; - var b = "safe"; - (a, b) = (sink(a) + source("t19.1"), sink(b) + source("t19.2")); - sink(a); // $ hasTaintFlow=t19.1 - sink(b); // $ hasTaintFlow=t19.2 + var a = "safe" + var b = "safe" + (a, b) = (sink(a) + source("t19.1"), sink(b) + source("t19.2")) + sink(a) // $ hasTaintFlow=t19.1 + sink(b) // $ hasTaintFlow=t19.2 }