diff --git a/swift/ql/lib/change-notes/2023-09-13-array-content-unification.md b/swift/ql/lib/change-notes/2023-09-13-array-content-unification.md new file mode 100644 index 00000000000..4185581839d --- /dev/null +++ b/swift/ql/lib/change-notes/2023-09-13-array-content-unification.md @@ -0,0 +1,5 @@ +--- +category: deprecated +--- + +* The `ArrayContent` type in the data flow library has been deprecated and made an alias for the `CollectionContent` type, to better reflect the hierarchy of the Swift standard library. Uses of `ArrayElement` in model files will be interpreted as referring to `CollectionContent`. diff --git a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll index f2e31b71f07..128883d125d 100644 --- a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll +++ b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll @@ -497,8 +497,9 @@ predicate parseContent(AccessPathToken component, Content content) { or parseEnum(component, content) or + // map legacy "ArrayElement" specification components to `CollectionContent` component.getName() = "ArrayElement" and - content instanceof Content::ArrayContent + content instanceof Content::CollectionContent or component.getName() = "CollectionElement" and content instanceof Content::CollectionContent diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index 3255afb19db..fb330d48ed9 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -297,7 +297,6 @@ private module Cached { TFieldContent(FieldDecl f) or TTupleContent(int index) { exists(any(TupleExpr te).getElement(index)) } or TEnumContent(ParamDecl f) { exists(EnumElementDecl d | d.getAParam() = f) } or - TArrayContent() or TCollectionContent() } @@ -842,7 +841,7 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { exists(ArrayExpr arr | node1.asExpr() = arr.getAnElement() and node2.asExpr() = arr and - c.isSingleton(any(Content::ArrayContent ac)) + c.isSingleton(any(Content::CollectionContent ac)) ) or // array assignment `a[n] = x` @@ -851,7 +850,7 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { node2.(PostUpdateNode).getPreUpdateNode().asExpr() = subscript.getBase() and subscript = assign.getDest() and subscript.getBase().getType() instanceof ArrayType and - c.isSingleton(any(Content::ArrayContent ac)) + c.isSingleton(any(Content::CollectionContent ac)) ) or // creation of an optional via implicit wrapping keypath component @@ -948,7 +947,7 @@ predicate readStep(Node node1, ContentSet c, Node node2) { ( c.isSingleton(any(Content::FieldContent ct | ct.getField() = component.getDeclRef())) or - c.isSingleton(any(Content::ArrayContent ac)) and + c.isSingleton(any(Content::CollectionContent ac)) and component.isSubscript() or c instanceof OptionalSomeContentSet and @@ -971,12 +970,7 @@ predicate readStep(Node node1, ContentSet c, Node node2) { exists(SubscriptExpr subscript | subscript.getBase() = node1.asExpr() and subscript = node2.asExpr() and - ( - subscript.getBase().getType() instanceof ArrayType and - c.isSingleton(any(Content::ArrayContent ac)) - or - c.isSingleton(any(Content::CollectionContent ac)) - ) + c.isSingleton(any(Content::CollectionContent ac)) ) or // read of a dictionary value via subscript operator @@ -1098,9 +1092,7 @@ class DataFlowExpr = Expr; * Holds if access paths with `c` at their head always should be tracked at high * precision. This disables adaptive access path precision for such access paths. */ -predicate forceHighPrecision(Content c) { - c instanceof Content::ArrayContent or c instanceof Content::CollectionContent -} +predicate forceHighPrecision(Content c) { c instanceof Content::CollectionContent } /** * Holds if the node `n` is unreachable when the call context is `call`. diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll index 04ab0e27a10..11d63134029 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll @@ -220,11 +220,6 @@ module Content { override string toString() { result = this.getSignature() } } - /** An element of an array at an unknown index */ - class ArrayContent extends Content, TArrayContent { - override string toString() { result = "Array element" } - } - /** * An element of a collection. This is a broad class including: * - elements of collections, such as `Set`. @@ -234,6 +229,11 @@ module Content { class CollectionContent extends Content, TCollectionContent { override string toString() { result = "Collection element" } } + + /** + * DEPRECATED: An element of a collection. This is an alias for the general CollectionContent. + */ + deprecated class ArrayContent = CollectionContent; } /** diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll index df677d86e90..a8c99277f46 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll @@ -129,11 +129,6 @@ private string getContentSpecific(ContentSet cs) { result = "EnumElement[" + c.getSignature() + "]" ) or - exists(Content::ArrayContent c | - cs.isSingleton(c) and - result = "ArrayElement" - ) - or exists(Content::CollectionContent c | cs.isSingleton(c) and result = "CollectionElement" diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll index 9d1fa9469bb..26ded1c5b56 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Array.qll @@ -19,20 +19,20 @@ private class ArraySummaries extends SummaryModelCsv { override predicate row(string row) { row = [ - ";Array;true;insert(_:at:);;;Argument[0];Argument[-1].ArrayElement;value", + ";Array;true;insert(_:at:);;;Argument[0];Argument[-1].CollectionElement;value", ";Array;true;insert(_:at:);;;Argument[1];Argument[-1];taint", ";Array;true;withUnsafeBufferPointer(_:);;;Argument[-1];Argument[0].Parameter[0].CollectionElement;taint", - ";Array;true;withUnsafeBufferPointer(_:);;;Argument[-1].ArrayElement;Argument[0].Parameter[0].CollectionElement;value", + ";Array;true;withUnsafeBufferPointer(_:);;;Argument[-1].CollectionElement;Argument[0].Parameter[0].CollectionElement;value", ";Array;true;withUnsafeBufferPointer(_:);;;Argument[0].ReturnValue;ReturnValue;value", ";Array;true;withUnsafeMutableBufferPointer(_:);;;Argument[-1];Argument[0].Parameter[0].CollectionElement;taint", - ";Array;true;withUnsafeMutableBufferPointer(_:);;;Argument[-1].ArrayElement;Argument[0].Parameter[0].CollectionElement;value", + ";Array;true;withUnsafeMutableBufferPointer(_:);;;Argument[-1].CollectionElement;Argument[0].Parameter[0].CollectionElement;value", ";Array;true;withUnsafeMutableBufferPointer(_:);;;Argument[0].Parameter[0].CollectionElement;Argument[-1].CollectionElement;value", ";Array;true;withUnsafeMutableBufferPointer(_:);;;Argument[0].ReturnValue;ReturnValue;value", ";Array;true;withUnsafeBytes(_:);;;Argument[-1];Argument[0].Parameter[0].CollectionElement;taint", - ";Array;true;withUnsafeBytes(_:);;;Argument[-1].ArrayElement;Argument[0].Parameter[0].CollectionElement;taint", + ";Array;true;withUnsafeBytes(_:);;;Argument[-1].CollectionElement;Argument[0].Parameter[0].CollectionElement;taint", ";Array;true;withUnsafeBytes(_:);;;Argument[0].ReturnValue;ReturnValue;value", ";Array;true;withUnsafeMutableBytes(_:);;;Argument[-1];Argument[0].Parameter[0].CollectionElement;taint", - ";Array;true;withUnsafeMutableBytes(_:);;;Argument[-1].ArrayElement;Argument[0].Parameter[0].CollectionElement;taint", + ";Array;true;withUnsafeMutableBytes(_:);;;Argument[-1].CollectionElement;Argument[0].Parameter[0].CollectionElement;taint", ";Array;true;withUnsafeMutableBytes(_:);;;Argument[0].Parameter[0].CollectionElement;Argument[-1].CollectionElement;value", ";Array;true;withUnsafeMutableBytes(_:);;;Argument[0].ReturnValue;ReturnValue;value", ";ContiguousArray;true;withUnsafeBufferPointer(_:);;;Argument[-1];Argument[0].Parameter[0].CollectionElement;taint", diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Collection.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Collection.qll index 119a71ae61e..279f0b8adb8 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Collection.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Collection.qll @@ -27,7 +27,6 @@ private class CollectionSummaries extends SummaryModelCsv { ";Collection;true;removeFirst();;;Argument[-1];ReturnValue;taint", ";Collection;true;popFirst();;;Argument[-1];ReturnValue;taint", ";Collection;true;randomElement();;;Argument[-1].CollectionElement;ReturnValue.OptionalSome;value", - ";Collection;true;randomElement();;;Argument[-1].ArrayElement;ReturnValue.OptionalSome;value", ";RangeReplaceableCollection;true;append(_:);;;Argument[0];Argument[-1];taint", ";RangeReplaceableCollection;true;append(contentsOf:);;;Argument[0];Argument[-1];taint", ";RangeReplaceableCollection;true;remove(at:);;;Argument[-1];ReturnValue;taint", @@ -38,7 +37,6 @@ private class CollectionSummaries extends SummaryModelCsv { ";BidirectionalCollection;true;last(where:);;;Argument[-1];ReturnValue;taint", ";BidirectionalCollection;true;popLast();;;Argument[-1];ReturnValue;taint", ";MutableCollection;true;withContiguousMutableStorageIfAvailable(_:);;;Argument[-1];Argument[0].Parameter[0].CollectionElement;taint", - ";MutableCollection;true;withContiguousMutableStorageIfAvailable(_:);;;Argument[-1].ArrayElement;Argument[0].Parameter[0].CollectionElement;value", ";MutableCollection;true;withContiguousMutableStorageIfAvailable(_:);;;Argument[-1].CollectionElement;Argument[0].Parameter[0].CollectionElement;value", ";MutableCollection;true;withContiguousMutableStorageIfAvailable(_:);;;Argument[0].Parameter[0].CollectionElement;Argument[-1].CollectionElement;value", ";MutableCollection;true;withContiguousMutableStorageIfAvailable(_:);;;Argument[0].ReturnValue;ReturnValue.OptionalSome;value", diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Sequence.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Sequence.qll index 0e9b1b05f97..3687cf772ee 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Sequence.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Sequence.qll @@ -26,7 +26,6 @@ private class SequenceSummaries extends SummaryModelCsv { ";Sequence;true;joined(separator:);;;Argument[-1..0];ReturnValue;taint", ";Sequence;true;first(where:);;;Argument[-1];ReturnValue;taint", ";Sequence;true;withContiguousStorageIfAvailable(_:);;;Argument[-1];Argument[0].Parameter[0].CollectionElement;taint", - ";Sequence;true;withContiguousStorageIfAvailable(_:);;;Argument[-1].ArrayElement;Argument[0].Parameter[0].CollectionElement;value", ";Sequence;true;withContiguousStorageIfAvailable(_:);;;Argument[-1].CollectionElement;Argument[0].Parameter[0].CollectionElement;value", ";Sequence;true;withContiguousStorageIfAvailable(_:);;;Argument[0].ReturnValue;ReturnValue.OptionalSome;value", ] diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Set.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Set.qll index e5198d043bb..91b7e627cfc 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Set.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Set.qll @@ -14,7 +14,7 @@ private class SetSummaries extends SummaryModelCsv { ";Set;true;insert(_:);;;Argument[-1].CollectionElement;ReturnValue.TupleElement[1];value", ";Set;true;insert(_:);;;Argument[0];Argument[-1].CollectionElement;value", ";Set;true;insert(_:);;;Argument[0];ReturnValue.TupleElement[1];value", - ";Set;true;init(_:);;;Argument[0].ArrayElement;ReturnValue.CollectionElement;value" + ";Set;true;init(_:);;;Argument[0].CollectionElement;ReturnValue.CollectionElement;value" ] } } diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll index f3e563d510b..4102940580a 100644 --- a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/String.qll @@ -34,7 +34,6 @@ private class StringSummaries extends SummaryModelCsv { row = [ ";StringProtocol;true;init(cString:);;;Argument[0];ReturnValue;taint", - ";StringProtocol;true;init(cString:);;;Argument[0].ArrayElement;ReturnValue;taint", ";StringProtocol;true;init(cString:);;;Argument[0].CollectionElement;ReturnValue;taint", ";StringProtocol;true;init(decoding:as:);;;Argument[0];ReturnValue;taint", ";StringProtocol;true;init(decodingCString:as:);;;Argument[0].OptionalSome.CollectionElement;ReturnValue.OptionalSome.TupleElement[0];taint", @@ -46,12 +45,12 @@ private class StringSummaries extends SummaryModelCsv { ";StringProtocol;true;cString(using:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;capitalized(with:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[0].OptionalSome.CollectionElement;taint", - ";StringProtocol;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[2].OptionalSome.CollectionElement.ArrayElement;taint", + ";StringProtocol;true;completePath(into:caseSensitive:matchesInto:filterTypes:);;;Argument[-1];Argument[2].OptionalSome.CollectionElement.CollectionElement;taint", ";StringProtocol;true;components(separatedBy:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;data(using:allowLossyConversion:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;folding(options:locale:);;;Argument[-1];ReturnValue;taint", - ";StringProtocol;true;getBytes(_:maxLength:usedLength:encoding:options:range:remaining:);;;Argument[-1];Argument[0].ArrayElement;taint", - ";StringProtocol;true;getCString(_:maxLength:encoding:);;;Argument[-1];Argument[0].ArrayElement;taint", + ";StringProtocol;true;getBytes(_:maxLength:usedLength:encoding:options:range:remaining:);;;Argument[-1];Argument[0].CollectionElement;taint", + ";StringProtocol;true;getCString(_:maxLength:encoding:);;;Argument[-1];Argument[0].CollectionElement;taint", ";StringProtocol;true;lowercased();;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;lowercased(with:);;;Argument[-1];ReturnValue;taint", ";StringProtocol;true;padding(toLength:withPad:startingAt:);;;Argument[-1];ReturnValue;taint", @@ -74,20 +73,18 @@ private class StringSummaries extends SummaryModelCsv { ";String;true;init(repeating:count:);;;Argument[0];ReturnValue;taint", ";String;true;init(data:encoding:);;;Argument[0];ReturnValue.OptionalSome;taint", ";String;true;init(validatingUTF8:);;;Argument[0];ReturnValue.OptionalSome;taint", - ";String;true;init(validatingUTF8:);;;Argument[0].ArrayElement;ReturnValue.OptionalSome;taint", ";String;true;init(validatingUTF8:);;;Argument[0].CollectionElement;ReturnValue.OptionalSome;taint", ";String;true;init(utf16CodeUnits:count:);;;Argument[0].CollectionElement;ReturnValue;taint", ";String;true;init(utf16CodeUnitsNoCopy:count:freeWhenDone:);;;Argument[0].CollectionElement;ReturnValue;taint", ";String;true;init(format:_:);;;Argument[0];ReturnValue;taint", - ";String;true;init(format:_:);;;Argument[1].ArrayElement;ReturnValue;taint", + ";String;true;init(format:_:);;;Argument[1].CollectionElement;ReturnValue;taint", ";String;true;init(format:arguments:);;;Argument[0];ReturnValue;taint", - ";String;true;init(format:arguments:);;;Argument[1].ArrayElement;ReturnValue;taint", + ";String;true;init(format:arguments:);;;Argument[1].CollectionElement;ReturnValue;taint", ";String;true;init(format:locale:_:);;;Argument[0];ReturnValue;taint", - ";String;true;init(format:locale:_:);;;Argument[2].ArrayElement;ReturnValue;taint", + ";String;true;init(format:locale:_:);;;Argument[2].CollectionElement;ReturnValue;taint", ";String;true;init(format:locale:arguments:);;;Argument[0];ReturnValue;taint", - ";String;true;init(format:locale:arguments:);;;Argument[2].ArrayElement;ReturnValue;taint", + ";String;true;init(format:locale:arguments:);;;Argument[2].CollectionElement;ReturnValue;taint", ";String;true;init(_:radix:uppercase:);;;Argument[0];ReturnValue;taint", - ";String;true;init(bytes:encoding:);;;Argument[0].ArrayElement;ReturnValue.OptionalSome;taint", ";String;true;init(bytes:encoding:);;;Argument[0].CollectionElement;ReturnValue.OptionalSome;taint", ";String;true;init(bytesNoCopy:length:encoding:freeWhenDone:);;;Argument[0].CollectionElement;ReturnValue.OptionalSome;taint", ";String;true;init(describing:);;;Argument[0];ReturnValue;taint", @@ -104,20 +101,16 @@ private class StringSummaries extends SummaryModelCsv { ";String;true;init(unicodeScalarLiteral:);;;Argument[0];ReturnValue;taint", ";String;true;init(extendedGraphemeClusterLiteral:);;;Argument[0];ReturnValue;taint", ";String;true;init(cString:encoding:);;;Argument[0];ReturnValue.OptionalSome;taint", - ";String;true;init(cString:encoding:);;;Argument[0].ArrayElement;ReturnValue.OptionalSome;taint", ";String;true;init(cString:encoding:);;;Argument[0].CollectionElement;ReturnValue.OptionalSome;taint", ";String;true;init(platformString:);;;Argument[0];ReturnValue;taint", - ";String;true;init(platformString:);;;Argument[0].ArrayElement;ReturnValue;taint", ";String;true;init(platformString:);;;Argument[0].CollectionElement;ReturnValue;taint", ";String;true;init(utf8String:);;;Argument[0];ReturnValue.OptionalSome;taint", - ";String;true;init(utf8String:);;;Argument[0].ArrayElement;ReturnValue.OptionalSome;taint", ";String;true;init(utf8String:);;;Argument[0].CollectionElement;ReturnValue.OptionalSome;taint", ";String;true;init(validating:);;;Argument[0];ReturnValue.OptionalSome;taint", ";String;true;init(validatingPlatformString:);;;Argument[0];ReturnValue.OptionalSome;taint", - ";String;true;init(validatingPlatformString:);;;Argument[0].ArrayElement;ReturnValue.OptionalSome;taint", ";String;true;init(validatingPlatformString:);;;Argument[0].CollectionElement;ReturnValue.OptionalSome;taint", ";String;true;localizedStringWithFormat(_:_:);;;Argument[0];ReturnValue;taint", - ";String;true;localizedStringWithFormat(_:_:);;;Argument[1].ArrayContent;ReturnValue;taint", + ";String;true;localizedStringWithFormat(_:_:);;;Argument[1].CollectionElement;ReturnValue;taint", ";String;true;write(_:);;;Argument[0];Argument[-1];taint", ";String;true;write(to:);;;Argument[-1];Argument[0];taint", ";String;true;insert(contentsOf:at:);;;Argument[0];Argument[-1];taint", diff --git a/swift/ql/lib/codeql/swift/security/UnsafeJsEvalQuery.qll b/swift/ql/lib/codeql/swift/security/UnsafeJsEvalQuery.qll index deebcd46e6b..af9305b3ef9 100644 --- a/swift/ql/lib/codeql/swift/security/UnsafeJsEvalQuery.qll +++ b/swift/ql/lib/codeql/swift/security/UnsafeJsEvalQuery.qll @@ -30,10 +30,7 @@ module UnsafeJsEvalConfig implements DataFlow::ConfigSig { or isAdditionalFlowStep(node, _) ) and - ( - c.getAReadContent() instanceof DataFlow::Content::ArrayContent or - c.getAReadContent() instanceof DataFlow::Content::CollectionContent - ) + c.getAReadContent() instanceof DataFlow::Content::CollectionContent } } diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected index d25f5ee0849..3a774f1b117 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected @@ -334,12 +334,12 @@ edges | test.swift:642:17:642:17 | KeyPathComponent [x] | test.swift:642:11:642:17 | exit #keyPath(...) | | test.swift:643:13:643:13 | s2 [s, x] | test.swift:642:11:642:17 | enter #keyPath(...) [s, x] | | test.swift:643:13:643:13 | s2 [s, x] | test.swift:643:13:643:26 | \\...[...] | -| test.swift:647:17:647:26 | [...] [Array element] | test.swift:649:15:649:15 | array [Array element] | -| test.swift:647:18:647:25 | call to source() | test.swift:647:17:647:26 | [...] [Array element] | -| test.swift:648:13:648:22 | enter #keyPath(...) [Array element] | test.swift:648:20:648:22 | KeyPathComponent [Array element] | -| test.swift:648:20:648:22 | KeyPathComponent [Array element] | test.swift:648:13:648:22 | exit #keyPath(...) | -| test.swift:649:15:649:15 | array [Array element] | test.swift:648:13:648:22 | enter #keyPath(...) [Array element] | -| test.swift:649:15:649:15 | array [Array element] | test.swift:649:15:649:31 | \\...[...] | +| test.swift:647:17:647:26 | [...] [Collection element] | test.swift:649:15:649:15 | array [Collection element] | +| test.swift:647:18:647:25 | call to source() | test.swift:647:17:647:26 | [...] [Collection element] | +| test.swift:648:13:648:22 | enter #keyPath(...) [Collection element] | test.swift:648:20:648:22 | KeyPathComponent [Collection element] | +| test.swift:648:20:648:22 | KeyPathComponent [Collection element] | test.swift:648:13:648:22 | exit #keyPath(...) | +| test.swift:649:15:649:15 | array [Collection element] | test.swift:648:13:648:22 | enter #keyPath(...) [Collection element] | +| test.swift:649:15:649:15 | array [Collection element] | test.swift:649:15:649:31 | \\...[...] | | test.swift:655:8:655:12 | s [some:0, x] | test.swift:656:14:656:14 | s [some:0, x] | | test.swift:656:5:656:5 | [post] self [s, some:0, x] | test.swift:655:3:657:3 | self[return] [s, some:0, x] | | test.swift:656:14:656:14 | s [some:0, x] | test.swift:656:5:656:5 | [post] self [s, some:0, x] | @@ -362,39 +362,36 @@ edges | test.swift:678:9:678:16 | call to source() | test.swift:681:15:681:15 | x | | test.swift:680:11:680:11 | x | test.swift:680:15:680:15 | [post] y | | test.swift:680:15:680:15 | [post] y | test.swift:682:15:682:15 | y | -| test.swift:688:5:688:5 | [post] arr1 [Array element] | test.swift:689:15:689:15 | arr1 [Array element] | -| test.swift:688:15:688:22 | call to source() | test.swift:688:5:688:5 | [post] arr1 [Array element] | -| test.swift:689:15:689:15 | arr1 [Array element] | test.swift:689:15:689:21 | ...[...] | -| test.swift:692:16:692:25 | [...] [Array element] | test.swift:693:15:693:15 | arr2 [Array element] | -| test.swift:692:17:692:24 | call to source() | test.swift:692:16:692:25 | [...] [Array element] | -| test.swift:693:15:693:15 | arr2 [Array element] | test.swift:693:15:693:21 | ...[...] | -| test.swift:695:18:695:29 | [...] [Array element, Array element] | test.swift:697:15:697:15 | matrix [Array element, Array element] | -| test.swift:695:19:695:28 | [...] [Array element] | test.swift:695:18:695:29 | [...] [Array element, Array element] | -| test.swift:695:20:695:27 | call to source() | test.swift:695:19:695:28 | [...] [Array element] | -| test.swift:697:15:697:15 | matrix [Array element, Array element] | test.swift:697:15:697:23 | ...[...] [Array element] | -| test.swift:697:15:697:23 | ...[...] [Array element] | test.swift:697:15:697:26 | ...[...] | -| test.swift:700:5:700:5 | [post] matrix2 [Array element, Array element] | test.swift:701:15:701:15 | matrix2 [Array element, Array element] | -| test.swift:700:5:700:5 | [post] matrix2 [Collection element, Array element] | test.swift:701:15:701:15 | matrix2 [Collection element, Array element] | -| test.swift:700:5:700:14 | [post] getter for ...[...] [Array element] | test.swift:700:5:700:5 | [post] matrix2 [Array element, Array element] | -| test.swift:700:5:700:14 | [post] getter for ...[...] [Array element] | test.swift:700:5:700:5 | [post] matrix2 [Collection element, Array element] | -| test.swift:700:21:700:28 | call to source() | test.swift:700:5:700:14 | [post] getter for ...[...] [Array element] | -| test.swift:701:15:701:15 | matrix2 [Array element, Array element] | test.swift:701:15:701:24 | ...[...] [Array element] | -| test.swift:701:15:701:15 | matrix2 [Collection element, Array element] | test.swift:701:15:701:24 | ...[...] [Array element] | -| test.swift:701:15:701:24 | ...[...] [Array element] | test.swift:701:15:701:27 | ...[...] | -| test.swift:712:5:712:5 | [post] arr6 [Array element] | test.swift:713:15:713:15 | arr6 [Array element] | -| test.swift:712:17:712:24 | call to source() | test.swift:712:5:712:5 | [post] arr6 [Array element] | -| test.swift:713:15:713:15 | arr6 [Array element] | test.swift:713:15:713:21 | ...[...] | -| test.swift:715:16:715:25 | [...] [Array element] | test.swift:716:15:716:15 | arr7 [Array element] | -| test.swift:715:17:715:24 | call to source() | test.swift:715:16:715:25 | [...] [Array element] | -| test.swift:716:15:716:15 | arr7 [Array element] | test.swift:716:15:716:34 | call to randomElement() [some:0] | +| test.swift:688:5:688:5 | [post] arr1 [Collection element] | test.swift:689:15:689:15 | arr1 [Collection element] | +| test.swift:688:15:688:22 | call to source() | test.swift:688:5:688:5 | [post] arr1 [Collection element] | +| test.swift:689:15:689:15 | arr1 [Collection element] | test.swift:689:15:689:21 | ...[...] | +| test.swift:692:16:692:25 | [...] [Collection element] | test.swift:693:15:693:15 | arr2 [Collection element] | +| test.swift:692:17:692:24 | call to source() | test.swift:692:16:692:25 | [...] [Collection element] | +| test.swift:693:15:693:15 | arr2 [Collection element] | test.swift:693:15:693:21 | ...[...] | +| test.swift:695:18:695:29 | [...] [Collection element, Collection element] | test.swift:697:15:697:15 | matrix [Collection element, Collection element] | +| test.swift:695:19:695:28 | [...] [Collection element] | test.swift:695:18:695:29 | [...] [Collection element, Collection element] | +| test.swift:695:20:695:27 | call to source() | test.swift:695:19:695:28 | [...] [Collection element] | +| test.swift:697:15:697:15 | matrix [Collection element, Collection element] | test.swift:697:15:697:23 | ...[...] [Collection element] | +| test.swift:697:15:697:23 | ...[...] [Collection element] | test.swift:697:15:697:26 | ...[...] | +| test.swift:700:5:700:5 | [post] matrix2 [Collection element, Collection element] | test.swift:701:15:701:15 | matrix2 [Collection element, Collection element] | +| test.swift:700:5:700:14 | [post] getter for ...[...] [Collection element] | test.swift:700:5:700:5 | [post] matrix2 [Collection element, Collection element] | +| test.swift:700:21:700:28 | call to source() | test.swift:700:5:700:14 | [post] getter for ...[...] [Collection element] | +| test.swift:701:15:701:15 | matrix2 [Collection element, Collection element] | test.swift:701:15:701:24 | ...[...] [Collection element] | +| test.swift:701:15:701:24 | ...[...] [Collection element] | test.swift:701:15:701:27 | ...[...] | +| test.swift:712:5:712:5 | [post] arr6 [Collection element] | test.swift:713:15:713:15 | arr6 [Collection element] | +| test.swift:712:17:712:24 | call to source() | test.swift:712:5:712:5 | [post] arr6 [Collection element] | +| test.swift:713:15:713:15 | arr6 [Collection element] | test.swift:713:15:713:21 | ...[...] | +| test.swift:715:16:715:25 | [...] [Collection element] | test.swift:716:15:716:15 | arr7 [Collection element] | +| test.swift:715:17:715:24 | call to source() | test.swift:715:16:715:25 | [...] [Collection element] | +| test.swift:716:15:716:15 | arr7 [Collection element] | test.swift:716:15:716:34 | call to randomElement() [some:0] | | test.swift:716:15:716:34 | call to randomElement() [some:0] | test.swift:716:15:716:35 | ...! | | test.swift:722:5:722:5 | [post] set1 [Collection element] | test.swift:723:15:723:15 | set1 [Collection element] | | test.swift:722:17:722:24 | call to source() | test.swift:722:5:722:5 | [post] set1 [Collection element] | | test.swift:723:15:723:15 | set1 [Collection element] | test.swift:723:15:723:34 | call to randomElement() [some:0] | | test.swift:723:15:723:34 | call to randomElement() [some:0] | test.swift:723:15:723:35 | ...! | | test.swift:725:16:725:30 | call to Set.init(_:) [Collection element] | test.swift:726:15:726:15 | set2 [Collection element] | -| test.swift:725:20:725:29 | [...] [Array element] | test.swift:725:16:725:30 | call to Set.init(_:) [Collection element] | -| test.swift:725:21:725:28 | call to source() | test.swift:725:20:725:29 | [...] [Array element] | +| test.swift:725:20:725:29 | [...] [Collection element] | test.swift:725:16:725:30 | call to Set.init(_:) [Collection element] | +| test.swift:725:21:725:28 | call to source() | test.swift:725:20:725:29 | [...] [Collection element] | | test.swift:726:15:726:15 | set2 [Collection element] | test.swift:726:15:726:34 | call to randomElement() [some:0] | | test.swift:726:15:726:34 | call to randomElement() [some:0] | test.swift:726:15:726:35 | ...! | | test.swift:731:9:731:9 | self [v2, some:0] | file://:0:0:0:0 | self [v2, some:0] | @@ -893,12 +890,12 @@ nodes | test.swift:642:17:642:17 | KeyPathComponent [x] | semmle.label | KeyPathComponent [x] | | test.swift:643:13:643:13 | s2 [s, x] | semmle.label | s2 [s, x] | | test.swift:643:13:643:26 | \\...[...] | semmle.label | \\...[...] | -| test.swift:647:17:647:26 | [...] [Array element] | semmle.label | [...] [Array element] | +| test.swift:647:17:647:26 | [...] [Collection element] | semmle.label | [...] [Collection element] | | test.swift:647:18:647:25 | call to source() | semmle.label | call to source() | -| test.swift:648:13:648:22 | enter #keyPath(...) [Array element] | semmle.label | enter #keyPath(...) [Array element] | +| test.swift:648:13:648:22 | enter #keyPath(...) [Collection element] | semmle.label | enter #keyPath(...) [Collection element] | | test.swift:648:13:648:22 | exit #keyPath(...) | semmle.label | exit #keyPath(...) | -| test.swift:648:20:648:22 | KeyPathComponent [Array element] | semmle.label | KeyPathComponent [Array element] | -| test.swift:649:15:649:15 | array [Array element] | semmle.label | array [Array element] | +| test.swift:648:20:648:22 | KeyPathComponent [Collection element] | semmle.label | KeyPathComponent [Collection element] | +| test.swift:649:15:649:15 | array [Collection element] | semmle.label | array [Collection element] | | test.swift:649:15:649:31 | \\...[...] | semmle.label | \\...[...] | | test.swift:655:3:657:3 | self[return] [s, some:0, x] | semmle.label | self[return] [s, some:0, x] | | test.swift:655:8:655:12 | s [some:0, x] | semmle.label | s [some:0, x] | @@ -924,35 +921,33 @@ nodes | test.swift:680:15:680:15 | [post] y | semmle.label | [post] y | | test.swift:681:15:681:15 | x | semmle.label | x | | test.swift:682:15:682:15 | y | semmle.label | y | -| test.swift:688:5:688:5 | [post] arr1 [Array element] | semmle.label | [post] arr1 [Array element] | +| test.swift:688:5:688:5 | [post] arr1 [Collection element] | semmle.label | [post] arr1 [Collection element] | | test.swift:688:15:688:22 | call to source() | semmle.label | call to source() | -| test.swift:689:15:689:15 | arr1 [Array element] | semmle.label | arr1 [Array element] | +| test.swift:689:15:689:15 | arr1 [Collection element] | semmle.label | arr1 [Collection element] | | test.swift:689:15:689:21 | ...[...] | semmle.label | ...[...] | -| test.swift:692:16:692:25 | [...] [Array element] | semmle.label | [...] [Array element] | +| test.swift:692:16:692:25 | [...] [Collection element] | semmle.label | [...] [Collection element] | | test.swift:692:17:692:24 | call to source() | semmle.label | call to source() | -| test.swift:693:15:693:15 | arr2 [Array element] | semmle.label | arr2 [Array element] | +| test.swift:693:15:693:15 | arr2 [Collection element] | semmle.label | arr2 [Collection element] | | test.swift:693:15:693:21 | ...[...] | semmle.label | ...[...] | -| test.swift:695:18:695:29 | [...] [Array element, Array element] | semmle.label | [...] [Array element, Array element] | -| test.swift:695:19:695:28 | [...] [Array element] | semmle.label | [...] [Array element] | +| test.swift:695:18:695:29 | [...] [Collection element, Collection element] | semmle.label | [...] [Collection element, Collection element] | +| test.swift:695:19:695:28 | [...] [Collection element] | semmle.label | [...] [Collection element] | | test.swift:695:20:695:27 | call to source() | semmle.label | call to source() | -| test.swift:697:15:697:15 | matrix [Array element, Array element] | semmle.label | matrix [Array element, Array element] | -| test.swift:697:15:697:23 | ...[...] [Array element] | semmle.label | ...[...] [Array element] | +| test.swift:697:15:697:15 | matrix [Collection element, Collection element] | semmle.label | matrix [Collection element, Collection element] | +| test.swift:697:15:697:23 | ...[...] [Collection element] | semmle.label | ...[...] [Collection element] | | test.swift:697:15:697:26 | ...[...] | semmle.label | ...[...] | -| test.swift:700:5:700:5 | [post] matrix2 [Array element, Array element] | semmle.label | [post] matrix2 [Array element, Array element] | -| test.swift:700:5:700:5 | [post] matrix2 [Collection element, Array element] | semmle.label | [post] matrix2 [Collection element, Array element] | -| test.swift:700:5:700:14 | [post] getter for ...[...] [Array element] | semmle.label | [post] getter for ...[...] [Array element] | +| test.swift:700:5:700:5 | [post] matrix2 [Collection element, Collection element] | semmle.label | [post] matrix2 [Collection element, Collection element] | +| test.swift:700:5:700:14 | [post] getter for ...[...] [Collection element] | semmle.label | [post] getter for ...[...] [Collection element] | | test.swift:700:21:700:28 | call to source() | semmle.label | call to source() | -| test.swift:701:15:701:15 | matrix2 [Array element, Array element] | semmle.label | matrix2 [Array element, Array element] | -| test.swift:701:15:701:15 | matrix2 [Collection element, Array element] | semmle.label | matrix2 [Collection element, Array element] | -| test.swift:701:15:701:24 | ...[...] [Array element] | semmle.label | ...[...] [Array element] | +| test.swift:701:15:701:15 | matrix2 [Collection element, Collection element] | semmle.label | matrix2 [Collection element, Collection element] | +| test.swift:701:15:701:24 | ...[...] [Collection element] | semmle.label | ...[...] [Collection element] | | test.swift:701:15:701:27 | ...[...] | semmle.label | ...[...] | -| test.swift:712:5:712:5 | [post] arr6 [Array element] | semmle.label | [post] arr6 [Array element] | +| test.swift:712:5:712:5 | [post] arr6 [Collection element] | semmle.label | [post] arr6 [Collection element] | | test.swift:712:17:712:24 | call to source() | semmle.label | call to source() | -| test.swift:713:15:713:15 | arr6 [Array element] | semmle.label | arr6 [Array element] | +| test.swift:713:15:713:15 | arr6 [Collection element] | semmle.label | arr6 [Collection element] | | test.swift:713:15:713:21 | ...[...] | semmle.label | ...[...] | -| test.swift:715:16:715:25 | [...] [Array element] | semmle.label | [...] [Array element] | +| test.swift:715:16:715:25 | [...] [Collection element] | semmle.label | [...] [Collection element] | | test.swift:715:17:715:24 | call to source() | semmle.label | call to source() | -| test.swift:716:15:716:15 | arr7 [Array element] | semmle.label | arr7 [Array element] | +| test.swift:716:15:716:15 | arr7 [Collection element] | semmle.label | arr7 [Collection element] | | test.swift:716:15:716:34 | call to randomElement() [some:0] | semmle.label | call to randomElement() [some:0] | | test.swift:716:15:716:35 | ...! | semmle.label | ...! | | test.swift:722:5:722:5 | [post] set1 [Collection element] | semmle.label | [post] set1 [Collection element] | @@ -961,7 +956,7 @@ nodes | test.swift:723:15:723:34 | call to randomElement() [some:0] | semmle.label | call to randomElement() [some:0] | | test.swift:723:15:723:35 | ...! | semmle.label | ...! | | test.swift:725:16:725:30 | call to Set.init(_:) [Collection element] | semmle.label | call to Set.init(_:) [Collection element] | -| test.swift:725:20:725:29 | [...] [Array element] | semmle.label | [...] [Array element] | +| test.swift:725:20:725:29 | [...] [Collection element] | semmle.label | [...] [Collection element] | | test.swift:725:21:725:28 | call to source() | semmle.label | call to source() | | test.swift:726:15:726:15 | set2 [Collection element] | semmle.label | set2 [Collection element] | | test.swift:726:15:726:34 | call to randomElement() [some:0] | semmle.label | call to randomElement() [some:0] | @@ -1128,7 +1123,7 @@ subpaths | test.swift:640:16:640:23 | call to source() | test.swift:617:8:617:11 | x | test.swift:617:3:619:3 | self[return] [x] | test.swift:640:11:640:24 | call to S.init(x:) [x] | | test.swift:641:18:641:18 | s [x] | test.swift:634:8:634:11 | s [x] | test.swift:634:3:636:3 | self[return] [s, x] | test.swift:641:12:641:19 | call to S2.init(s:) [s, x] | | test.swift:643:13:643:13 | s2 [s, x] | test.swift:642:11:642:17 | enter #keyPath(...) [s, x] | test.swift:642:11:642:17 | exit #keyPath(...) | test.swift:643:13:643:26 | \\...[...] | -| test.swift:649:15:649:15 | array [Array element] | test.swift:648:13:648:22 | enter #keyPath(...) [Array element] | test.swift:648:13:648:22 | exit #keyPath(...) | test.swift:649:15:649:31 | \\...[...] | +| test.swift:649:15:649:15 | array [Collection element] | test.swift:648:13:648:22 | enter #keyPath(...) [Collection element] | test.swift:648:13:648:22 | exit #keyPath(...) | test.swift:649:15:649:31 | \\...[...] | | test.swift:661:18:661:25 | call to source() | test.swift:617:8:617:11 | x | test.swift:617:3:619:3 | self[return] [x] | test.swift:661:13:661:26 | call to S.init(x:) [x] | | test.swift:662:29:662:29 | s [some:0, x] | test.swift:655:8:655:12 | s [some:0, x] | test.swift:655:3:657:3 | self[return] [s, some:0, x] | test.swift:662:14:662:30 | call to S2_Optional.init(s:) [s, some:0, x] | | test.swift:664:15:664:15 | s2 [s, some:0, x] | test.swift:663:13:663:29 | enter #keyPath(...) [s, some:0, x] | test.swift:663:13:663:29 | exit #keyPath(...) [some:0] | test.swift:664:15:664:28 | \\...[...] [some:0] |