Merge pull request #13947 from rdmarsh2/rdmarsh2/swift/dictionary-flow-tuples

Swift: collection/tuple content for dictionary flow
This commit is contained in:
Mathias Vorreiter Pedersen
2023-09-07 22:05:10 +01:00
committed by GitHub
8 changed files with 298 additions and 3 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added flow steps through `Dictionary` keys and values.

View File

@@ -9,6 +9,7 @@ private import codeql.swift.dataflow.FlowSummary as FlowSummary
private import codeql.swift.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import codeql.swift.frameworks.StandardLibrary.PointerTypes
private import codeql.swift.frameworks.StandardLibrary.Array
private import codeql.swift.frameworks.StandardLibrary.Dictionary
/** Gets the callable in which this node occurs. */
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.(NodeImpl).getEnclosingCallable() }
@@ -114,6 +115,9 @@ private module Cached {
any(ApplyExpr apply).getQualifier(), any(TupleElementExpr te).getSubExpr(),
any(SubscriptExpr se).getBase()
])
} or
TDictionarySubscriptNode(SubscriptExpr e) {
e.getBase().getType().getCanonicalType() instanceof CanonicalDictionaryType
}
private predicate localSsaFlowStepUseUse(Ssa::Definition def, Node nodeFrom, Node nodeTo) {
@@ -296,6 +300,28 @@ import Cached
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) { n instanceof FlowSummaryNode }
/**
* The intermediate node for a dictionary subscript operation `dict[key]`. In a write, this is used
* as the destination of the `storeStep`s that add `TupleContent`s and the source of the storeStep
* that adds `CollectionContent`. In a read, this is the destination of the `readStep` that pops
* `CollectionContent` and the source of the `readStep` that pops `TupleContent[0]`
*/
private class DictionarySubscriptNode extends NodeImpl, TDictionarySubscriptNode {
SubscriptExpr expr;
DictionarySubscriptNode() { this = TDictionarySubscriptNode(expr) }
override DataFlowCallable getEnclosingCallable() {
result.asSourceCallable() = expr.getEnclosingCallable()
}
override string toStringImpl() { result = "DictionarySubscriptNode" }
override Location getLocationImpl() { result = expr.getLocation() }
SubscriptExpr getExpr() { result = expr }
}
private module ParameterNodes {
abstract class ParameterNodeImpl extends NodeImpl {
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { none() }
@@ -735,6 +761,32 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
c instanceof OptionalSomeContentSet
)
or
// assignment to a dictionary value via subscript operator, with intermediate step
// `dict[key] = value`
exists(AssignExpr assign, SubscriptExpr subscript |
subscript = assign.getDest() and
(
subscript.getArgument(0).getExpr() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 0))
or
assign.getSource() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
or
node1.(DictionarySubscriptNode).getExpr() = subscript and
node2.(PostUpdateNode).getPreUpdateNode().asExpr() = subscript.getBase() and
c.isSingleton(any(Content::CollectionContent cc))
)
)
or
// creation of a dictionary `[key: value, ...]`
exists(DictionaryExpr dict |
node1.asExpr() = dict.getAnElement() and
node2.asExpr() = dict and
c.isSingleton(any(Content::CollectionContent cc))
)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
}
@@ -826,6 +878,17 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
)
)
or
// read of a dictionary value via subscript operator
exists(SubscriptExpr subscript |
subscript.getBase() = node1.asExpr() and
node2.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::CollectionContent cc))
or
subscript = node2.asExpr() and
node1.(DictionarySubscriptNode).getExpr() = subscript and
c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = 1))
)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
}
@@ -836,7 +899,12 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
* in `x.f = newValue`.
*/
predicate clearsContent(Node n, ContentSet c) {
n = any(PostUpdateNode pun | storeStep(_, c, pun)).getPreUpdateNode()
n = any(PostUpdateNode pun | storeStep(_, c, pun)).getPreUpdateNode() and
(
c.isSingleton(any(Content::FieldContent fc)) or
c.isSingleton(any(Content::TupleContent tc)) or
c.isSingleton(any(Content::EnumContent ec))
)
}
/**

View File

@@ -9,7 +9,7 @@ private import codeql.swift.dataflow.ExternalFlow
* An instance of the `Array` type.
*/
class ArrayType extends Type {
ArrayType() { this.getName().matches("Array<%") or this.getName().matches("[%]") }
ArrayType() { this.getCanonicalType().getName().matches("Array<%") }
}
/**

View File

@@ -0,0 +1,27 @@
/**
* Provides models for the Swift `Dictionary` class.
*/
import swift
private import codeql.swift.dataflow.ExternalFlow
/**
* An instance of the `Dictionary` type.
*/
class CanonicalDictionaryType extends BoundGenericType {
CanonicalDictionaryType() { this.getName().matches("Dictionary<%") }
}
/**
* A model for `Dictionary` and related class members that permit data flow.
*/
private class DictionarySummaries extends SummaryModelCsv {
override predicate row(string row) {
row =
[
";Dictionary;true;updateValue(_:forKey:);;;Argument[0];Argument[-1].CollectionElement.TupleElement[1];value",
";Dictionary;true;updateValue(_:forKey:);;;Argument[1];Argument[-1].CollectionElement.TupleElement[0];value",
";Dictionary;true;updateValue(_:forKey:);;;Argument[-1].CollectionElement.TupleElement[1];ReturnValue.OptionalSome;value"
]
}
}

View File

@@ -438,6 +438,49 @@ edges
| test.swift:766:29:766:29 | KeyPathComponent [x] | test.swift:766:13:766:29 | exit #keyPath(...) |
| test.swift:767:15:767:15 | s2 [s, some:0, x] | test.swift:766:13:766:29 | enter #keyPath(...) [s, some:0, x] |
| test.swift:767:15:767:15 | s2 [s, some:0, x] | test.swift:767:15:767:28 | \\...[...] |
| test.swift:774:5:774:5 | [post] dict1 [Collection element, Tuple element at index 1] | test.swift:776:15:776:15 | dict1 [Collection element, Tuple element at index 1] |
| test.swift:774:5:774:12 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:774:5:774:5 | [post] dict1 [Collection element, Tuple element at index 1] |
| test.swift:774:16:774:23 | call to source() | test.swift:774:5:774:12 | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:776:15:776:15 | dict1 [Collection element, Tuple element at index 1] | test.swift:776:15:776:22 | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:776:15:776:22 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:776:15:776:22 | ...[...] |
| test.swift:786:17:786:29 | [...] [Collection element, Tuple element at index 1] | test.swift:787:15:787:15 | dict3 [Collection element, Tuple element at index 1] |
| test.swift:786:17:786:29 | [...] [Collection element, Tuple element at index 1] | test.swift:789:5:789:5 | dict3 [Collection element, Tuple element at index 1] |
| test.swift:786:17:786:29 | [...] [Collection element, Tuple element at index 1] | test.swift:792:15:792:15 | dict3 [Collection element, Tuple element at index 1] |
| test.swift:786:18:786:28 | (...) [Tuple element at index 1] | test.swift:786:17:786:29 | [...] [Collection element, Tuple element at index 1] |
| test.swift:786:21:786:28 | call to source() | test.swift:786:18:786:28 | (...) [Tuple element at index 1] |
| test.swift:787:15:787:15 | dict3 [Collection element, Tuple element at index 1] | test.swift:787:15:787:22 | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:787:15:787:22 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:787:15:787:22 | ...[...] |
| test.swift:789:5:789:5 | [post] dict3 [Collection element, Tuple element at index 0] | test.swift:791:15:791:15 | dict3 [Collection element, Tuple element at index 0] |
| test.swift:789:5:789:5 | [post] dict3 [Collection element, Tuple element at index 1] | test.swift:792:15:792:15 | dict3 [Collection element, Tuple element at index 1] |
| test.swift:789:5:789:5 | dict3 [Collection element, Tuple element at index 1] | test.swift:789:5:789:19 | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:789:5:789:19 | DictionarySubscriptNode [Tuple element at index 0] | test.swift:789:5:789:5 | [post] dict3 [Collection element, Tuple element at index 0] |
| test.swift:789:5:789:19 | DictionarySubscriptNode [Tuple element at index 1] | test.swift:789:5:789:5 | [post] dict3 [Collection element, Tuple element at index 1] |
| test.swift:789:11:789:18 | call to source() | test.swift:789:5:789:19 | DictionarySubscriptNode [Tuple element at index 0] |
| test.swift:791:15:791:15 | dict3 [Collection element, Tuple element at index 0] | test.swift:791:15:791:35 | call to randomElement() [some:0, Tuple element at index 0] |
| test.swift:791:15:791:35 | call to randomElement() [some:0, Tuple element at index 0] | test.swift:791:15:791:36 | ...! [Tuple element at index 0] |
| test.swift:791:15:791:36 | ...! [Tuple element at index 0] | test.swift:791:15:791:38 | .0 |
| test.swift:792:15:792:15 | dict3 [Collection element, Tuple element at index 1] | test.swift:792:15:792:35 | call to randomElement() [some:0, Tuple element at index 1] |
| test.swift:792:15:792:35 | call to randomElement() [some:0, Tuple element at index 1] | test.swift:792:15:792:36 | ...! [Tuple element at index 1] |
| test.swift:792:15:792:36 | ...! [Tuple element at index 1] | test.swift:792:15:792:38 | .1 |
| test.swift:799:17:799:28 | [...] [Collection element, Tuple element at index 1] | test.swift:800:15:800:15 | dict4 [Collection element, Tuple element at index 1] |
| test.swift:799:17:799:28 | [...] [Collection element, Tuple element at index 1] | test.swift:801:15:801:15 | dict4 [Collection element, Tuple element at index 1] |
| test.swift:799:17:799:28 | [...] [Collection element, Tuple element at index 1] | test.swift:803:15:803:15 | dict4 [Collection element, Tuple element at index 1] |
| test.swift:799:18:799:27 | (...) [Tuple element at index 1] | test.swift:799:17:799:28 | [...] [Collection element, Tuple element at index 1] |
| test.swift:799:20:799:27 | call to source() | test.swift:799:18:799:27 | (...) [Tuple element at index 1] |
| test.swift:800:15:800:15 | [post] dict4 [Collection element, Tuple element at index 0] | test.swift:802:15:802:15 | dict4 [Collection element, Tuple element at index 0] |
| test.swift:800:15:800:15 | dict4 [Collection element, Tuple element at index 1] | test.swift:800:15:800:52 | call to updateValue(_:forKey:) [some:0] |
| test.swift:800:15:800:52 | call to updateValue(_:forKey:) [some:0] | test.swift:800:15:800:53 | ...! |
| test.swift:800:44:800:51 | call to source() | test.swift:800:15:800:15 | [post] dict4 [Collection element, Tuple element at index 0] |
| test.swift:801:15:801:15 | [post] dict4 [Collection element, Tuple element at index 1] | test.swift:803:15:803:15 | dict4 [Collection element, Tuple element at index 1] |
| test.swift:801:15:801:15 | dict4 [Collection element, Tuple element at index 1] | test.swift:801:15:801:52 | call to updateValue(_:forKey:) [some:0] |
| test.swift:801:15:801:52 | call to updateValue(_:forKey:) [some:0] | test.swift:801:15:801:53 | ...! |
| test.swift:801:33:801:40 | call to source() | test.swift:801:15:801:15 | [post] dict4 [Collection element, Tuple element at index 1] |
| test.swift:802:15:802:15 | dict4 [Collection element, Tuple element at index 0] | test.swift:802:15:802:35 | call to randomElement() [some:0, Tuple element at index 0] |
| test.swift:802:15:802:35 | call to randomElement() [some:0, Tuple element at index 0] | test.swift:802:15:802:36 | ...! [Tuple element at index 0] |
| test.swift:802:15:802:36 | ...! [Tuple element at index 0] | test.swift:802:15:802:38 | .0 |
| test.swift:803:15:803:15 | dict4 [Collection element, Tuple element at index 1] | test.swift:803:15:803:35 | call to randomElement() [some:0, Tuple element at index 1] |
| test.swift:803:15:803:35 | call to randomElement() [some:0, Tuple element at index 1] | test.swift:803:15:803:36 | ...! [Tuple element at index 1] |
| test.swift:803:15:803:36 | ...! [Tuple element at index 1] | test.swift:803:15:803:38 | .1 |
nodes
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
| file://:0:0:0:0 | .str | semmle.label | .str |
@@ -915,6 +958,53 @@ nodes
| test.swift:766:29:766:29 | KeyPathComponent [x] | semmle.label | KeyPathComponent [x] |
| test.swift:767:15:767:15 | s2 [s, some:0, x] | semmle.label | s2 [s, some:0, x] |
| test.swift:767:15:767:28 | \\...[...] | semmle.label | \\...[...] |
| test.swift:774:5:774:5 | [post] dict1 [Collection element, Tuple element at index 1] | semmle.label | [post] dict1 [Collection element, Tuple element at index 1] |
| test.swift:774:5:774:12 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:774:16:774:23 | call to source() | semmle.label | call to source() |
| test.swift:776:15:776:15 | dict1 [Collection element, Tuple element at index 1] | semmle.label | dict1 [Collection element, Tuple element at index 1] |
| test.swift:776:15:776:22 | ...[...] | semmle.label | ...[...] |
| test.swift:776:15:776:22 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:786:17:786:29 | [...] [Collection element, Tuple element at index 1] | semmle.label | [...] [Collection element, Tuple element at index 1] |
| test.swift:786:18:786:28 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
| test.swift:786:21:786:28 | call to source() | semmle.label | call to source() |
| test.swift:787:15:787:15 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
| test.swift:787:15:787:22 | ...[...] | semmle.label | ...[...] |
| test.swift:787:15:787:22 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:789:5:789:5 | [post] dict3 [Collection element, Tuple element at index 0] | semmle.label | [post] dict3 [Collection element, Tuple element at index 0] |
| test.swift:789:5:789:5 | [post] dict3 [Collection element, Tuple element at index 1] | semmle.label | [post] dict3 [Collection element, Tuple element at index 1] |
| test.swift:789:5:789:5 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
| test.swift:789:5:789:19 | DictionarySubscriptNode [Tuple element at index 0] | semmle.label | DictionarySubscriptNode [Tuple element at index 0] |
| test.swift:789:5:789:19 | DictionarySubscriptNode [Tuple element at index 1] | semmle.label | DictionarySubscriptNode [Tuple element at index 1] |
| test.swift:789:11:789:18 | call to source() | semmle.label | call to source() |
| test.swift:791:15:791:15 | dict3 [Collection element, Tuple element at index 0] | semmle.label | dict3 [Collection element, Tuple element at index 0] |
| test.swift:791:15:791:35 | call to randomElement() [some:0, Tuple element at index 0] | semmle.label | call to randomElement() [some:0, Tuple element at index 0] |
| test.swift:791:15:791:36 | ...! [Tuple element at index 0] | semmle.label | ...! [Tuple element at index 0] |
| test.swift:791:15:791:38 | .0 | semmle.label | .0 |
| test.swift:792:15:792:15 | dict3 [Collection element, Tuple element at index 1] | semmle.label | dict3 [Collection element, Tuple element at index 1] |
| test.swift:792:15:792:35 | call to randomElement() [some:0, Tuple element at index 1] | semmle.label | call to randomElement() [some:0, Tuple element at index 1] |
| test.swift:792:15:792:36 | ...! [Tuple element at index 1] | semmle.label | ...! [Tuple element at index 1] |
| test.swift:792:15:792:38 | .1 | semmle.label | .1 |
| test.swift:799:17:799:28 | [...] [Collection element, Tuple element at index 1] | semmle.label | [...] [Collection element, Tuple element at index 1] |
| test.swift:799:18:799:27 | (...) [Tuple element at index 1] | semmle.label | (...) [Tuple element at index 1] |
| test.swift:799:20:799:27 | call to source() | semmle.label | call to source() |
| test.swift:800:15:800:15 | [post] dict4 [Collection element, Tuple element at index 0] | semmle.label | [post] dict4 [Collection element, Tuple element at index 0] |
| test.swift:800:15:800:15 | dict4 [Collection element, Tuple element at index 1] | semmle.label | dict4 [Collection element, Tuple element at index 1] |
| test.swift:800:15:800:52 | call to updateValue(_:forKey:) [some:0] | semmle.label | call to updateValue(_:forKey:) [some:0] |
| test.swift:800:15:800:53 | ...! | semmle.label | ...! |
| test.swift:800:44:800:51 | call to source() | semmle.label | call to source() |
| test.swift:801:15:801:15 | [post] dict4 [Collection element, Tuple element at index 1] | semmle.label | [post] dict4 [Collection element, Tuple element at index 1] |
| test.swift:801:15:801:15 | dict4 [Collection element, Tuple element at index 1] | semmle.label | dict4 [Collection element, Tuple element at index 1] |
| test.swift:801:15:801:52 | call to updateValue(_:forKey:) [some:0] | semmle.label | call to updateValue(_:forKey:) [some:0] |
| test.swift:801:15:801:53 | ...! | semmle.label | ...! |
| test.swift:801:33:801:40 | call to source() | semmle.label | call to source() |
| test.swift:802:15:802:15 | dict4 [Collection element, Tuple element at index 0] | semmle.label | dict4 [Collection element, Tuple element at index 0] |
| test.swift:802:15:802:35 | call to randomElement() [some:0, Tuple element at index 0] | semmle.label | call to randomElement() [some:0, Tuple element at index 0] |
| test.swift:802:15:802:36 | ...! [Tuple element at index 0] | semmle.label | ...! [Tuple element at index 0] |
| test.swift:802:15:802:38 | .0 | semmle.label | .0 |
| test.swift:803:15:803:15 | dict4 [Collection element, Tuple element at index 1] | semmle.label | dict4 [Collection element, Tuple element at index 1] |
| test.swift:803:15:803:35 | call to randomElement() [some:0, Tuple element at index 1] | semmle.label | call to randomElement() [some:0, Tuple element at index 1] |
| test.swift:803:15:803:36 | ...! [Tuple element at index 1] | semmle.label | ...! [Tuple element at index 1] |
| test.swift:803:15:803:38 | .1 | semmle.label | .1 |
subpaths
| test.swift:75:22:75:22 | x | test.swift:65:16:65:28 | arg1 | test.swift:65:1:70:1 | arg2[return] | test.swift:75:32:75:32 | [post] y |
| test.swift:114:19:114:19 | arg | test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg | test.swift:114:12:114:22 | call to ... |
@@ -1070,3 +1160,12 @@ subpaths
| test.swift:756:15:756:21 | ...! | test.swift:746:14:746:21 | call to source() | test.swift:756:15:756:21 | ...! | result |
| test.swift:757:15:757:19 | .v3 | test.swift:747:14:747:21 | call to source() | test.swift:757:15:757:19 | .v3 | result |
| test.swift:767:15:767:28 | \\...[...] | test.swift:764:18:764:25 | call to source() | test.swift:767:15:767:28 | \\...[...] | result |
| test.swift:776:15:776:22 | ...[...] | test.swift:774:16:774:23 | call to source() | test.swift:776:15:776:22 | ...[...] | result |
| test.swift:787:15:787:22 | ...[...] | test.swift:786:21:786:28 | call to source() | test.swift:787:15:787:22 | ...[...] | result |
| test.swift:791:15:791:38 | .0 | test.swift:789:11:789:18 | call to source() | test.swift:791:15:791:38 | .0 | result |
| test.swift:792:15:792:38 | .1 | test.swift:786:21:786:28 | call to source() | test.swift:792:15:792:38 | .1 | result |
| test.swift:800:15:800:53 | ...! | test.swift:799:20:799:27 | call to source() | test.swift:800:15:800:53 | ...! | result |
| test.swift:801:15:801:53 | ...! | test.swift:799:20:799:27 | call to source() | test.swift:801:15:801:53 | ...! | result |
| test.swift:802:15:802:38 | .0 | test.swift:800:44:800:51 | call to source() | test.swift:802:15:802:38 | .0 | result |
| test.swift:803:15:803:38 | .1 | test.swift:799:20:799:27 | call to source() | test.swift:803:15:803:38 | .1 | result |
| test.swift:803:15:803:38 | .1 | test.swift:801:33:801:40 | call to source() | test.swift:803:15:803:38 | .1 | result |

View File

@@ -924,3 +924,62 @@
| test.swift:766:9:766:9 | f | test.swift:766:9:766:9 | SSA def(f) |
| test.swift:766:13:766:29 | #keyPath(...) | test.swift:766:9:766:9 | f |
| test.swift:766:13:766:29 | enter #keyPath(...) | test.swift:766:26:766:26 | KeyPathComponent |
| test.swift:771:9:771:9 | SSA def(dict1) | test.swift:772:15:772:15 | dict1 |
| test.swift:771:9:771:9 | dict1 | test.swift:771:9:771:9 | SSA def(dict1) |
| test.swift:771:17:771:31 | [...] | test.swift:771:9:771:9 | dict1 |
| test.swift:772:15:772:15 | &... | test.swift:774:5:774:5 | dict1 |
| test.swift:772:15:772:15 | [post] dict1 | test.swift:772:15:772:15 | &... |
| test.swift:772:15:772:15 | dict1 | test.swift:772:15:772:15 | &... |
| test.swift:774:5:774:5 | &... | test.swift:776:15:776:15 | dict1 |
| test.swift:774:5:774:5 | [post] dict1 | test.swift:774:5:774:5 | &... |
| test.swift:774:5:774:5 | dict1 | test.swift:774:5:774:5 | &... |
| test.swift:776:15:776:15 | [post] dict1 | test.swift:776:15:776:15 | &... |
| test.swift:776:15:776:15 | dict1 | test.swift:776:15:776:15 | &... |
| test.swift:778:9:778:9 | SSA def(dict2) | test.swift:779:15:779:15 | dict2 |
| test.swift:778:9:778:9 | dict2 | test.swift:778:9:778:9 | SSA def(dict2) |
| test.swift:778:17:778:29 | [...] | test.swift:778:9:778:9 | dict2 |
| test.swift:779:15:779:15 | &... | test.swift:781:25:781:25 | dict2 |
| test.swift:779:15:779:15 | [post] dict2 | test.swift:779:15:779:15 | &... |
| test.swift:779:15:779:15 | dict2 | test.swift:779:15:779:15 | &... |
| test.swift:781:10:781:10 | SSA def(key) | test.swift:782:19:782:19 | key |
| test.swift:781:10:781:10 | key | test.swift:781:10:781:10 | SSA def(key) |
| test.swift:781:15:781:15 | SSA def(value) | test.swift:783:19:783:19 | value |
| test.swift:781:15:781:15 | value | test.swift:781:15:781:15 | SSA def(value) |
| test.swift:786:9:786:9 | SSA def(dict3) | test.swift:787:15:787:15 | dict3 |
| test.swift:786:9:786:9 | dict3 | test.swift:786:9:786:9 | SSA def(dict3) |
| test.swift:786:17:786:29 | [...] | test.swift:786:9:786:9 | dict3 |
| test.swift:787:15:787:15 | &... | test.swift:789:5:789:5 | dict3 |
| test.swift:787:15:787:15 | [post] dict3 | test.swift:787:15:787:15 | &... |
| test.swift:787:15:787:15 | dict3 | test.swift:787:15:787:15 | &... |
| test.swift:789:5:789:5 | &... | test.swift:791:15:791:15 | dict3 |
| test.swift:789:5:789:5 | [post] dict3 | test.swift:789:5:789:5 | &... |
| test.swift:789:5:789:5 | dict3 | test.swift:789:5:789:5 | &... |
| test.swift:791:15:791:15 | [post] dict3 | test.swift:792:15:792:15 | dict3 |
| test.swift:791:15:791:15 | dict3 | test.swift:792:15:792:15 | dict3 |
| test.swift:791:15:791:35 | call to randomElement() | test.swift:791:15:791:36 | ...! |
| test.swift:792:15:792:15 | [post] dict3 | test.swift:794:25:794:25 | dict3 |
| test.swift:792:15:792:15 | dict3 | test.swift:794:25:794:25 | dict3 |
| test.swift:792:15:792:35 | call to randomElement() | test.swift:792:15:792:36 | ...! |
| test.swift:794:10:794:10 | SSA def(key) | test.swift:795:19:795:19 | key |
| test.swift:794:10:794:10 | key | test.swift:794:10:794:10 | SSA def(key) |
| test.swift:794:15:794:15 | SSA def(value) | test.swift:796:19:796:19 | value |
| test.swift:794:15:794:15 | value | test.swift:794:15:794:15 | SSA def(value) |
| test.swift:799:9:799:9 | SSA def(dict4) | test.swift:800:15:800:15 | dict4 |
| test.swift:799:9:799:9 | dict4 | test.swift:799:9:799:9 | SSA def(dict4) |
| test.swift:799:17:799:28 | [...] | test.swift:799:9:799:9 | dict4 |
| test.swift:800:15:800:15 | &... | test.swift:801:15:801:15 | dict4 |
| test.swift:800:15:800:15 | [post] dict4 | test.swift:800:15:800:15 | &... |
| test.swift:800:15:800:15 | dict4 | test.swift:800:15:800:15 | &... |
| test.swift:800:15:800:52 | call to updateValue(_:forKey:) | test.swift:800:15:800:53 | ...! |
| test.swift:801:15:801:15 | &... | test.swift:802:15:802:15 | dict4 |
| test.swift:801:15:801:15 | [post] dict4 | test.swift:801:15:801:15 | &... |
| test.swift:801:15:801:15 | dict4 | test.swift:801:15:801:15 | &... |
| test.swift:801:15:801:52 | call to updateValue(_:forKey:) | test.swift:801:15:801:53 | ...! |
| test.swift:802:15:802:15 | [post] dict4 | test.swift:803:15:803:15 | dict4 |
| test.swift:802:15:802:15 | dict4 | test.swift:803:15:803:15 | dict4 |
| test.swift:802:15:802:35 | call to randomElement() | test.swift:802:15:802:36 | ...! |
| test.swift:803:15:803:15 | [post] dict4 | test.swift:804:15:804:15 | dict4 |
| test.swift:803:15:803:15 | dict4 | test.swift:804:15:804:15 | dict4 |
| test.swift:803:15:803:35 | call to randomElement() | test.swift:803:15:803:36 | ...! |
| test.swift:804:15:804:15 | [post] dict4 | test.swift:805:15:805:15 | dict4 |
| test.swift:804:15:804:15 | dict4 | test.swift:805:15:805:15 | dict4 |

View File

@@ -766,3 +766,41 @@ func testOptionalKeyPathForce() {
let f = \S2_Optional.s!.x
sink(arg: s2[keyPath: f]) // $ flow=764
}
func testDictionary() {
var dict1 = [1:2, 3:4, 5:6]
sink(arg: dict1[1])
dict1[1] = source()
sink(arg: dict1[1]) // $ flow=774
var dict2 = [source(): 1]
sink(arg: dict2[1])
for (key, value) in dict2 {
sink(arg: key) // $ MISSING: flow=778
sink(arg: value)
}
var dict3 = [1: source()]
sink(arg: dict3[1]) // $ flow=786
dict3[source()] = 2
sink(arg: dict3.randomElement()!.0) // $ flow=789
sink(arg: dict3.randomElement()!.1) // $ flow=786
for (key, value) in dict3 {
sink(arg: key) // $ MISSING: flow=789
sink(arg: value) // $ MISSING: flow=786
}
var dict4 = [1:source()]
sink(arg: dict4.updateValue(1, forKey: source())!) // $ flow=799
sink(arg: dict4.updateValue(source(), forKey: 2)!) // $ SPURIOUS: flow=799
sink(arg: dict4.randomElement()!.0) // $ flow=800
sink(arg: dict4.randomElement()!.1) // $ flow=799 flow=801
sink(arg: dict4.keys.randomElement()) // $ MISSING: flow=800
sink(arg: dict4.values.randomElement()) // $ MISSING: flow=799 flow=801
}

View File

@@ -161,7 +161,7 @@ func taintCollections(array: inout Array<Int>, contiguousArray: inout Contiguous
dictionary[0] = source2()
sink(arg: dictionary)
sink(arg: dictionary[0]!) // $ MISSING: tainted=162
sink(arg: dictionary[0]!) // $ tainted=162
dictionary.withContiguousStorageIfAvailable({
buffer in
sink(arg: buffer)