mirror of
https://github.com/github/codeql.git
synced 2026-05-05 13:45:19 +02:00
Merge pull request #13947 from rdmarsh2/rdmarsh2/swift/dictionary-flow-tuples
Swift: collection/tuple content for dictionary flow
This commit is contained in:
4
swift/ql/lib/change-notes/2023-08-11-dictionary-flow.md
Normal file
4
swift/ql/lib/change-notes/2023-08-11-dictionary-flow.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added flow steps through `Dictionary` keys and values.
|
||||
@@ -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))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<%") }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user