Skip to content

Commit 246d5c5

Browse files
committed
Swift: flow through keypath force components
1 parent 5a76b9f commit 246d5c5

File tree

4 files changed

+61
-0
lines changed

4 files changed

+61
-0
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,14 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
789789
or
790790
c.isSingleton(any(Content::ArrayContent ac)) and
791791
component.isSubscript()
792+
or
793+
c.isSingleton(any(Content::EnumContent ec, EnumElementDecl eed |
794+
ec.getParam() = eed.getParam(0) and
795+
eed.getEnclosingDecl().asNominalTypeDecl().getName() = "Optional"
796+
|
797+
ec
798+
)) and
799+
component.isOptionalForcing()
792800
)
793801
|
794802
// the next node is either the next element in the chain

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ edges
333333
| test.swift:648:20:648:22 | KeyPathComponent [Array element] | test.swift:648:13:648:22 | exit #keyPath(...) |
334334
| test.swift:649:15:649:15 | array [Array element] | test.swift:648:13:648:22 | enter #keyPath(...) [Array element] |
335335
| test.swift:649:15:649:15 | array [Array element] | test.swift:649:15:649:31 | \\...[...] |
336+
| test.swift:655:8:655:12 | s [some:0, x] | test.swift:656:14:656:14 | s [some:0, x] |
337+
| test.swift:656:5:656:5 | [post] self [s, some:0, x] | test.swift:655:3:657:3 | self[return] [s, some:0, x] |
338+
| test.swift:656:14:656:14 | s [some:0, x] | test.swift:656:5:656:5 | [post] self [s, some:0, x] |
336339
| test.swift:668:13:668:20 | call to source() | test.swift:676:15:676:15 | y |
337340
| test.swift:678:9:678:16 | call to source() | test.swift:680:11:680:11 | x |
338341
| test.swift:678:9:678:16 | call to source() | test.swift:681:15:681:15 | x |
@@ -404,6 +407,19 @@ edges
404407
| test.swift:756:15:756:19 | .v2 [some:0] | test.swift:756:15:756:21 | ...! |
405408
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:732:9:732:9 | self [v3] |
406409
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:757:15:757:19 | .v3 |
410+
| test.swift:764:13:764:26 | call to S.init(x:) [x] | test.swift:765:29:765:29 | s [x] |
411+
| test.swift:764:18:764:25 | call to source() | test.swift:617:8:617:11 | x |
412+
| test.swift:764:18:764:25 | call to source() | test.swift:764:13:764:26 | call to S.init(x:) [x] |
413+
| test.swift:765:14:765:30 | call to S2_Optional.init(s:) [s, some:0, x] | test.swift:767:15:767:15 | s2 [s, some:0, x] |
414+
| test.swift:765:29:765:29 | s [some:0, x] | test.swift:655:8:655:12 | s [some:0, x] |
415+
| test.swift:765:29:765:29 | s [some:0, x] | test.swift:765:14:765:30 | call to S2_Optional.init(s:) [s, some:0, x] |
416+
| test.swift:765:29:765:29 | s [x] | test.swift:765:29:765:29 | s [some:0, x] |
417+
| test.swift:766:13:766:29 | enter #keyPath(...) [s, some:0, x] | test.swift:766:26:766:26 | KeyPathComponent [s, some:0, x] |
418+
| test.swift:766:26:766:26 | KeyPathComponent [s, some:0, x] | test.swift:766:26:766:26 | KeyPathComponent [some:0, x] |
419+
| test.swift:766:26:766:26 | KeyPathComponent [some:0, x] | test.swift:766:29:766:29 | KeyPathComponent [x] |
420+
| test.swift:766:29:766:29 | KeyPathComponent [x] | test.swift:766:13:766:29 | exit #keyPath(...) |
421+
| test.swift:767:15:767:15 | s2 [s, some:0, x] | test.swift:766:13:766:29 | enter #keyPath(...) [s, some:0, x] |
422+
| test.swift:767:15:767:15 | s2 [s, some:0, x] | test.swift:767:15:767:28 | \\...[...] |
407423
nodes
408424
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
409425
| file://:0:0:0:0 | .str | semmle.label | .str |
@@ -771,6 +787,10 @@ nodes
771787
| test.swift:648:20:648:22 | KeyPathComponent [Array element] | semmle.label | KeyPathComponent [Array element] |
772788
| test.swift:649:15:649:15 | array [Array element] | semmle.label | array [Array element] |
773789
| test.swift:649:15:649:31 | \\...[...] | semmle.label | \\...[...] |
790+
| test.swift:655:3:657:3 | self[return] [s, some:0, x] | semmle.label | self[return] [s, some:0, x] |
791+
| test.swift:655:8:655:12 | s [some:0, x] | semmle.label | s [some:0, x] |
792+
| test.swift:656:5:656:5 | [post] self [s, some:0, x] | semmle.label | [post] self [s, some:0, x] |
793+
| test.swift:656:14:656:14 | s [some:0, x] | semmle.label | s [some:0, x] |
774794
| test.swift:668:13:668:20 | call to source() | semmle.label | call to source() |
775795
| test.swift:676:15:676:15 | y | semmle.label | y |
776796
| test.swift:678:9:678:16 | call to source() | semmle.label | call to source() |
@@ -849,6 +869,18 @@ nodes
849869
| test.swift:756:15:756:21 | ...! | semmle.label | ...! |
850870
| test.swift:757:15:757:15 | mo1 [v3] | semmle.label | mo1 [v3] |
851871
| test.swift:757:15:757:19 | .v3 | semmle.label | .v3 |
872+
| test.swift:764:13:764:26 | call to S.init(x:) [x] | semmle.label | call to S.init(x:) [x] |
873+
| test.swift:764:18:764:25 | call to source() | semmle.label | call to source() |
874+
| test.swift:765:14:765:30 | call to S2_Optional.init(s:) [s, some:0, x] | semmle.label | call to S2_Optional.init(s:) [s, some:0, x] |
875+
| test.swift:765:29:765:29 | s [some:0, x] | semmle.label | s [some:0, x] |
876+
| test.swift:765:29:765:29 | s [x] | semmle.label | s [x] |
877+
| test.swift:766:13:766:29 | enter #keyPath(...) [s, some:0, x] | semmle.label | enter #keyPath(...) [s, some:0, x] |
878+
| test.swift:766:13:766:29 | exit #keyPath(...) | semmle.label | exit #keyPath(...) |
879+
| test.swift:766:26:766:26 | KeyPathComponent [s, some:0, x] | semmle.label | KeyPathComponent [s, some:0, x] |
880+
| test.swift:766:26:766:26 | KeyPathComponent [some:0, x] | semmle.label | KeyPathComponent [some:0, x] |
881+
| test.swift:766:29:766:29 | KeyPathComponent [x] | semmle.label | KeyPathComponent [x] |
882+
| test.swift:767:15:767:15 | s2 [s, some:0, x] | semmle.label | s2 [s, some:0, x] |
883+
| test.swift:767:15:767:28 | \\...[...] | semmle.label | \\...[...] |
852884
subpaths
853885
| 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 |
854886
| 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 ... |
@@ -897,6 +929,9 @@ subpaths
897929
| test.swift:756:15:756:15 | mo1 [v2, some:0] | test.swift:731:9:731:9 | self [v2, some:0] | file://:0:0:0:0 | .v2 [some:0] | test.swift:756:15:756:19 | .v2 [some:0] |
898930
| test.swift:756:15:756:15 | mo1 [v2] | test.swift:731:9:731:9 | self [v2] | file://:0:0:0:0 | .v2 | test.swift:756:15:756:19 | .v2 |
899931
| test.swift:757:15:757:15 | mo1 [v3] | test.swift:732:9:732:9 | self [v3] | file://:0:0:0:0 | .v3 | test.swift:757:15:757:19 | .v3 |
932+
| test.swift:764:18:764:25 | call to source() | test.swift:617:8:617:11 | x | test.swift:617:3:619:3 | self[return] [x] | test.swift:764:13:764:26 | call to S.init(x:) [x] |
933+
| test.swift:765:29:765: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:765:14:765:30 | call to S2_Optional.init(s:) [s, some:0, x] |
934+
| 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:766:13:766:29 | exit #keyPath(...) | test.swift:767:15:767:28 | \\...[...] |
900935
#select
901936
| test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:7:15:7:15 | t1 | result |
902937
| test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:9:15:9:15 | t1 | result |
@@ -996,3 +1031,4 @@ subpaths
9961031
| test.swift:754:15:754:15 | v3 | test.swift:744:10:744:17 | call to source() | test.swift:754:15:754:15 | v3 | result |
9971032
| test.swift:756:15:756:21 | ...! | test.swift:746:14:746:21 | call to source() | test.swift:756:15:756:21 | ...! | result |
9981033
| test.swift:757:15:757:19 | .v3 | test.swift:747:14:747:21 | call to source() | test.swift:757:15:757:19 | .v3 | result |
1034+
| test.swift:767:15:767:28 | \\...[...] | test.swift:764:18:764:25 | call to source() | test.swift:767:15:767:28 | \\...[...] | result |

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,3 +913,13 @@
913913
| test.swift:759:15:759:15 | mo2 | test.swift:760:15:760:15 | mo2 |
914914
| test.swift:759:15:759:20 | .v2 | test.swift:759:15:759:22 | ...! |
915915
| test.swift:760:15:760:15 | mo2 | test.swift:760:15:760:18 | ...! |
916+
| test.swift:764:9:764:9 | SSA def(s) | test.swift:765:29:765:29 | s |
917+
| test.swift:764:9:764:9 | s | test.swift:764:9:764:9 | SSA def(s) |
918+
| test.swift:764:13:764:26 | call to S.init(x:) | test.swift:764:9:764:9 | s |
919+
| test.swift:765:9:765:9 | SSA def(s2) | test.swift:767:15:767:15 | s2 |
920+
| test.swift:765:9:765:9 | s2 | test.swift:765:9:765:9 | SSA def(s2) |
921+
| test.swift:765:14:765:30 | call to S2_Optional.init(s:) | test.swift:765:9:765:9 | s2 |
922+
| test.swift:766:9:766:9 | SSA def(f) | test.swift:767:27:767:27 | f |
923+
| test.swift:766:9:766:9 | f | test.swift:766:9:766:9 | SSA def(f) |
924+
| test.swift:766:13:766:29 | #keyPath(...) | test.swift:766:9:766:9 | f |
925+
| test.swift:766:13:766:29 | enter #keyPath(...) | test.swift:766:26:766:26 | KeyPathComponent |

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,3 +759,10 @@ func testWriteOptional() {
759759
sink(arg: mo2!.v2!) // $ MISSING:flow=749
760760
sink(arg: mo2!.v3) // $ MISSING:flow=750
761761
}
762+
763+
func testOptionalKeyPathForce() {
764+
let s = S(x: source())
765+
let s2 = S2_Optional(s: s)
766+
let f = \S2_Optional.s!.x
767+
sink(arg: s2[keyPath: f]) // $ flow=764
768+
}

0 commit comments

Comments
 (0)