Skip to content

Commit 022a066

Browse files
authored
Merge pull request github#13838 from rdmarsh2/rdmarsh2/swift/set-content
Swift: add SetContent for data flow
2 parents eeaa361 + 07650af commit 022a066

File tree

11 files changed

+127
-2
lines changed

11 files changed

+127
-2
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: majorAnalysis
3+
---
4+
* Added `DataFlow::CollectionContent`, which will enable more accurate flow through collections.

swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,9 @@ predicate parseContent(AccessPathToken component, Content content) {
492492
or
493493
component.getName() = "ArrayElement" and
494494
content instanceof Content::ArrayContent
495+
or
496+
component.getName() = "CollectionElement" and
497+
content instanceof Content::CollectionContent
495498
}
496499

497500
cached

swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ private module Cached {
256256
TFieldContent(FieldDecl f) or
257257
TTupleContent(int index) { exists(any(TupleExpr te).getElement(index)) } or
258258
TEnumContent(ParamDecl f) { exists(EnumElementDecl d | d.getAParam() = f) } or
259-
TArrayContent()
259+
TArrayContent() or
260+
TCollectionContent()
260261
}
261262

262263
/**
@@ -797,6 +798,9 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
797798
subscript.getBase().getType() instanceof ArrayType and
798799
c.isSingleton(any(Content::ArrayContent ac))
799800
)
801+
or
802+
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
803+
node2.(FlowSummaryNode).getSummaryNode())
800804
}
801805

802806
/**
@@ -898,7 +902,9 @@ class DataFlowExpr = Expr;
898902
* Holds if access paths with `c` at their head always should be tracked at high
899903
* precision. This disables adaptive access path precision for such access paths.
900904
*/
901-
predicate forceHighPrecision(Content c) { c instanceof Content::ArrayContent }
905+
predicate forceHighPrecision(Content c) {
906+
c instanceof Content::ArrayContent or c instanceof Content::CollectionContent
907+
}
902908

903909
/**
904910
* Holds if the node `n` is unreachable when the call context is `call`.

swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ module Content {
224224
class ArrayContent extends Content, TArrayContent {
225225
override string toString() { result = "Array element" }
226226
}
227+
228+
/** An element of a collection. */
229+
class CollectionContent extends Content, TCollectionContent {
230+
override string toString() { result = "Collection element" }
231+
}
227232
}
228233

229234
/**

swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,20 @@ private string getContentSpecific(ContentSet cs) {
110110
result = "Field[" + c.getField().getName() + "]"
111111
)
112112
or
113+
exists(Content::EnumContent c |
114+
cs.isSingleton(c) and
115+
result = "EnumElement[" + c.getSignature() + "]"
116+
)
117+
or
113118
exists(Content::ArrayContent c |
114119
cs.isSingleton(c) and
115120
result = "ArrayElement"
116121
)
122+
or
123+
exists(Content::CollectionContent c |
124+
cs.isSingleton(c) and
125+
result = "CollectionElement"
126+
)
117127
}
118128

119129
/** Gets the textual representation of a summary component in the format used for MaD models. */
@@ -125,6 +135,16 @@ string getMadRepresentationSpecific(SummaryComponent sc) {
125135
not rk = getReturnValueKind() and
126136
result = "ReturnValue" + "[" + rk + "]"
127137
)
138+
or
139+
exists(ContentSet c |
140+
sc = TWithoutContentSummaryComponent(c) and
141+
result = "WithoutContent" + c.toString()
142+
)
143+
or
144+
exists(ContentSet c |
145+
sc = TWithContentSummaryComponent(c) and
146+
result = "WithContent" + c.toString()
147+
)
128148
}
129149

130150
/** Gets the textual representation of a parameter position in the format used for flow summaries. */

swift/ql/lib/codeql/swift/frameworks/StandardLibrary/Collection.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ private class CollectionSummaries extends SummaryModelCsv {
2626
";Collection;true;split(separator:maxSplits:omittingEmptySubsequences:);;;Argument[-1];ReturnValue;taint",
2727
";Collection;true;removeFirst();;;Argument[-1];ReturnValue;taint",
2828
";Collection;true;popFirst();;;Argument[-1];ReturnValue;taint",
29+
";Collection;true;randomElement();;;Argument[-1].CollectionElement;ReturnValue.OptionalSome;value",
30+
";Collection;true;randomElement();;;Argument[-1].ArrayElement;ReturnValue.OptionalSome;value",
2931
";RangeReplaceableCollection;true;append(_:);;;Argument[0];Argument[-1];taint",
3032
";RangeReplaceableCollection;true;append(contentsOf:);;;Argument[0];Argument[-1];taint",
3133
";RangeReplaceableCollection;true;remove(at:);;;Argument[-1];ReturnValue;taint",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Provides models for `Set` and related Swift classes.
3+
*/
4+
5+
private import codeql.swift.dataflow.ExternalFlow
6+
7+
/**
8+
* A model for `Set` and related class members that permit data flow.
9+
*/
10+
private class SetSummaries extends SummaryModelCsv {
11+
override predicate row(string row) {
12+
row =
13+
[
14+
";Set;true;insert(_:);;;Argument[-1].CollectionElement;ReturnValue.TupleElement[1];value",
15+
";Set;true;insert(_:);;;Argument[0];Argument[-1].CollectionElement;value",
16+
";Set;true;insert(_:);;;Argument[0];ReturnValue.TupleElement[1];value",
17+
";Set;true;init(_:);;;Argument[0].ArrayElement;ReturnValue.CollectionElement;value"
18+
]
19+
}
20+
}

swift/ql/lib/codeql/swift/frameworks/StandardLibrary/StandardLibrary.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ private import NsObject
1515
private import NsString
1616
private import NsUrl
1717
private import Sequence
18+
private import Set
1819
private import String
1920
private import Url
2021
private import UrlSession

swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,19 @@ edges
336336
| test.swift:693:5:693:5 | [post] arr6 [Array element] | test.swift:694:15:694:15 | arr6 [Array element] |
337337
| test.swift:693:17:693:24 | call to source() | test.swift:693:5:693:5 | [post] arr6 [Array element] |
338338
| test.swift:694:15:694:15 | arr6 [Array element] | test.swift:694:15:694:21 | ...[...] |
339+
| test.swift:696:16:696:25 | [...] [Array element] | test.swift:697:15:697:15 | arr7 [Array element] |
340+
| test.swift:696:17:696:24 | call to source() | test.swift:696:16:696:25 | [...] [Array element] |
341+
| test.swift:697:15:697:15 | arr7 [Array element] | test.swift:697:15:697:34 | call to randomElement() [some:0] |
342+
| test.swift:697:15:697:34 | call to randomElement() [some:0] | test.swift:697:15:697:35 | ...! |
343+
| test.swift:703:5:703:5 | [post] set1 [Collection element] | test.swift:704:15:704:15 | set1 [Collection element] |
344+
| test.swift:703:17:703:24 | call to source() | test.swift:703:5:703:5 | [post] set1 [Collection element] |
345+
| test.swift:704:15:704:15 | set1 [Collection element] | test.swift:704:15:704:34 | call to randomElement() [some:0] |
346+
| test.swift:704:15:704:34 | call to randomElement() [some:0] | test.swift:704:15:704:35 | ...! |
347+
| test.swift:706:16:706:30 | call to Set<Element>.init(_:) [Collection element] | test.swift:707:15:707:15 | set2 [Collection element] |
348+
| test.swift:706:20:706:29 | [...] [Array element] | test.swift:706:16:706:30 | call to Set<Element>.init(_:) [Collection element] |
349+
| test.swift:706:21:706:28 | call to source() | test.swift:706:20:706:29 | [...] [Array element] |
350+
| test.swift:707:15:707:15 | set2 [Collection element] | test.swift:707:15:707:34 | call to randomElement() [some:0] |
351+
| test.swift:707:15:707:34 | call to randomElement() [some:0] | test.swift:707:15:707:35 | ...! |
339352
nodes
340353
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
341354
| file://:0:0:0:0 | .str | semmle.label | .str |
@@ -706,6 +719,22 @@ nodes
706719
| test.swift:693:17:693:24 | call to source() | semmle.label | call to source() |
707720
| test.swift:694:15:694:15 | arr6 [Array element] | semmle.label | arr6 [Array element] |
708721
| test.swift:694:15:694:21 | ...[...] | semmle.label | ...[...] |
722+
| test.swift:696:16:696:25 | [...] [Array element] | semmle.label | [...] [Array element] |
723+
| test.swift:696:17:696:24 | call to source() | semmle.label | call to source() |
724+
| test.swift:697:15:697:15 | arr7 [Array element] | semmle.label | arr7 [Array element] |
725+
| test.swift:697:15:697:34 | call to randomElement() [some:0] | semmle.label | call to randomElement() [some:0] |
726+
| test.swift:697:15:697:35 | ...! | semmle.label | ...! |
727+
| test.swift:703:5:703:5 | [post] set1 [Collection element] | semmle.label | [post] set1 [Collection element] |
728+
| test.swift:703:17:703:24 | call to source() | semmle.label | call to source() |
729+
| test.swift:704:15:704:15 | set1 [Collection element] | semmle.label | set1 [Collection element] |
730+
| test.swift:704:15:704:34 | call to randomElement() [some:0] | semmle.label | call to randomElement() [some:0] |
731+
| test.swift:704:15:704:35 | ...! | semmle.label | ...! |
732+
| test.swift:706:16:706:30 | call to Set<Element>.init(_:) [Collection element] | semmle.label | call to Set<Element>.init(_:) [Collection element] |
733+
| test.swift:706:20:706:29 | [...] [Array element] | semmle.label | [...] [Array element] |
734+
| test.swift:706:21:706:28 | call to source() | semmle.label | call to source() |
735+
| test.swift:707:15:707:15 | set2 [Collection element] | semmle.label | set2 [Collection element] |
736+
| test.swift:707:15:707:34 | call to randomElement() [some:0] | semmle.label | call to randomElement() [some:0] |
737+
| test.swift:707:15:707:35 | ...! | semmle.label | ...! |
709738
subpaths
710739
| 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 |
711740
| 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 ... |
@@ -835,3 +864,6 @@ subpaths
835864
| test.swift:678:15:678:26 | ...[...] | test.swift:676:20:676:27 | call to source() | test.swift:678:15:678:26 | ...[...] | result |
836865
| test.swift:682:15:682:27 | ...[...] | test.swift:681:21:681:28 | call to source() | test.swift:682:15:682:27 | ...[...] | result |
837866
| test.swift:694:15:694:21 | ...[...] | test.swift:693:17:693:24 | call to source() | test.swift:694:15:694:21 | ...[...] | result |
867+
| test.swift:697:15:697:35 | ...! | test.swift:696:17:696:24 | call to source() | test.swift:697:15:697:35 | ...! | result |
868+
| test.swift:704:15:704:35 | ...! | test.swift:703:17:703:24 | call to source() | test.swift:704:15:704:35 | ...! | result |
869+
| test.swift:707:15:707:35 | ...! | test.swift:706:21:706:28 | call to source() | test.swift:707:15:707:35 | ...! | result |

swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,3 +811,22 @@
811811
| test.swift:693:5:693:5 | arr6 | test.swift:693:5:693:5 | &... |
812812
| test.swift:694:15:694:15 | [post] arr6 | test.swift:694:15:694:15 | &... |
813813
| test.swift:694:15:694:15 | arr6 | test.swift:694:15:694:15 | &... |
814+
| test.swift:696:9:696:9 | SSA def(arr7) | test.swift:697:15:697:15 | arr7 |
815+
| test.swift:696:9:696:9 | arr7 | test.swift:696:9:696:9 | SSA def(arr7) |
816+
| test.swift:696:16:696:25 | [...] | test.swift:696:9:696:9 | arr7 |
817+
| test.swift:697:15:697:34 | call to randomElement() | test.swift:697:15:697:35 | ...! |
818+
| test.swift:701:9:701:9 | SSA def(set1) | test.swift:702:15:702:15 | set1 |
819+
| test.swift:701:9:701:9 | set1 | test.swift:701:9:701:9 | SSA def(set1) |
820+
| test.swift:701:9:701:15 | ... as ... | test.swift:701:9:701:9 | set1 |
821+
| test.swift:701:21:701:27 | [...] | test.swift:701:9:701:15 | ... as ... |
822+
| test.swift:702:15:702:15 | [post] set1 | test.swift:703:5:703:5 | set1 |
823+
| test.swift:702:15:702:15 | set1 | test.swift:703:5:703:5 | set1 |
824+
| test.swift:702:15:702:34 | call to randomElement() | test.swift:702:15:702:35 | ...! |
825+
| test.swift:703:5:703:5 | &... | test.swift:704:15:704:15 | set1 |
826+
| test.swift:703:5:703:5 | [post] set1 | test.swift:703:5:703:5 | &... |
827+
| test.swift:703:5:703:5 | set1 | test.swift:703:5:703:5 | &... |
828+
| test.swift:704:15:704:34 | call to randomElement() | test.swift:704:15:704:35 | ...! |
829+
| test.swift:706:9:706:9 | SSA def(set2) | test.swift:707:15:707:15 | set2 |
830+
| test.swift:706:9:706:9 | set2 | test.swift:706:9:706:9 | SSA def(set2) |
831+
| test.swift:706:16:706:30 | call to Set<Element>.init(_:) | test.swift:706:9:706:9 | set2 |
832+
| test.swift:707:15:707:34 | call to randomElement() | test.swift:707:15:707:35 | ...! |

0 commit comments

Comments
 (0)