From c7fb8de5f9018f75f8b0b1d1777165802b9cabde Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 4 Aug 2023 19:33:48 +0100 Subject: [PATCH 1/4] Swift: Test ForceValueExpr content reads. --- .../dataflow/dataflow/DataFlow.expected | 86 +++++++++++++++++++ .../dataflow/dataflow/LocalFlow.expected | 64 ++++++++++++++ .../dataflow/dataflow/test.swift | 34 ++++++++ 3 files changed, 184 insertions(+) diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected index bab6db77c24..eb4b787609d 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected @@ -1,9 +1,15 @@ edges | file://:0:0:0:0 | self [a, x] | file://:0:0:0:0 | .a [x] | | file://:0:0:0:0 | self [str] | file://:0:0:0:0 | .str | +| file://:0:0:0:0 | self [v2, some:0] | file://:0:0:0:0 | .v2 [some:0] | +| file://:0:0:0:0 | self [v2] | file://:0:0:0:0 | .v2 | +| file://:0:0:0:0 | self [v3] | file://:0:0:0:0 | .v3 | | file://:0:0:0:0 | self [x, some:0] | file://:0:0:0:0 | .x [some:0] | | file://:0:0:0:0 | self [x] | file://:0:0:0:0 | .x | +| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v2] | +| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v3] | | file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [x] | +| file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [v2, some:0] | | file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [x, some:0] | | test.swift:6:19:6:26 | call to source() | test.swift:7:15:7:15 | t1 | | test.swift:6:19:6:26 | call to source() | test.swift:9:15:9:15 | t1 | @@ -336,18 +342,61 @@ edges | test.swift:693:5:693:5 | [post] arr6 [Array element] | test.swift:694:15:694:15 | arr6 [Array element] | | test.swift:693:17:693:24 | call to source() | test.swift:693:5:693:5 | [post] arr6 [Array element] | | test.swift:694:15:694:15 | arr6 [Array element] | test.swift:694:15:694:21 | ...[...] | +| test.swift:699:9:699:9 | self [v2, some:0] | file://:0:0:0:0 | self [v2, some:0] | +| test.swift:699:9:699:9 | self [v2] | file://:0:0:0:0 | self [v2] | +| test.swift:699:9:699:9 | value | file://:0:0:0:0 | value | +| test.swift:699:9:699:9 | value [some:0] | file://:0:0:0:0 | value [some:0] | +| test.swift:700:9:700:9 | self [v3] | file://:0:0:0:0 | self [v3] | +| test.swift:700:9:700:9 | value | file://:0:0:0:0 | value | +| test.swift:711:10:711:17 | call to source() | test.swift:711:10:711:17 | call to source() [some:0] | +| test.swift:711:10:711:17 | call to source() | test.swift:721:15:721:17 | ...! | +| test.swift:711:10:711:17 | call to source() [some:0] | test.swift:721:15:721:15 | v2 [some:0] | +| test.swift:712:10:712:17 | call to source() | test.swift:722:15:722:15 | v3 | +| test.swift:714:5:714:5 | [post] mo1 [v2, some:0] | test.swift:715:5:715:5 | mo1 [v2, some:0] | +| test.swift:714:5:714:5 | [post] mo1 [v2] | test.swift:715:5:715:5 | mo1 [v2] | +| test.swift:714:14:714:21 | call to source() | test.swift:699:9:699:9 | value | +| test.swift:714:14:714:21 | call to source() | test.swift:714:5:714:5 | [post] mo1 [v2] | +| test.swift:714:14:714:21 | call to source() | test.swift:714:14:714:21 | call to source() [some:0] | +| test.swift:714:14:714:21 | call to source() [some:0] | test.swift:699:9:699:9 | value [some:0] | +| test.swift:714:14:714:21 | call to source() [some:0] | test.swift:714:5:714:5 | [post] mo1 [v2, some:0] | +| test.swift:715:5:715:5 | [post] mo1 [v3] | test.swift:725:15:725:15 | mo1 [v3] | +| test.swift:715:5:715:5 | mo1 [v2, some:0] | test.swift:724:15:724:15 | mo1 [v2, some:0] | +| test.swift:715:5:715:5 | mo1 [v2] | test.swift:724:15:724:15 | mo1 [v2] | +| test.swift:715:14:715:21 | call to source() | test.swift:700:9:700:9 | value | +| test.swift:715:14:715:21 | call to source() | test.swift:715:5:715:5 | [post] mo1 [v3] | +| test.swift:721:15:721:15 | v2 [some:0] | test.swift:721:15:721:17 | ...! | +| test.swift:724:15:724:15 | mo1 [v2, some:0] | test.swift:699:9:699:9 | self [v2, some:0] | +| test.swift:724:15:724:15 | mo1 [v2, some:0] | test.swift:724:15:724:19 | .v2 [some:0] | +| test.swift:724:15:724:15 | mo1 [v2] | test.swift:699:9:699:9 | self [v2] | +| test.swift:724:15:724:15 | mo1 [v2] | test.swift:724:15:724:19 | .v2 | +| test.swift:724:15:724:19 | .v2 | test.swift:724:15:724:21 | ...! | +| test.swift:724:15:724:19 | .v2 [some:0] | test.swift:724:15:724:21 | ...! | +| test.swift:725:15:725:15 | mo1 [v3] | test.swift:700:9:700:9 | self [v3] | +| test.swift:725:15:725:15 | mo1 [v3] | test.swift:725:15:725:19 | .v3 | nodes | file://:0:0:0:0 | .a [x] | semmle.label | .a [x] | | file://:0:0:0:0 | .str | semmle.label | .str | +| file://:0:0:0:0 | .v2 | semmle.label | .v2 | +| file://:0:0:0:0 | .v2 [some:0] | semmle.label | .v2 [some:0] | +| file://:0:0:0:0 | .v3 | semmle.label | .v3 | | file://:0:0:0:0 | .x | semmle.label | .x | | file://:0:0:0:0 | .x [some:0] | semmle.label | .x [some:0] | +| file://:0:0:0:0 | [post] self [v2, some:0] | semmle.label | [post] self [v2, some:0] | +| file://:0:0:0:0 | [post] self [v2] | semmle.label | [post] self [v2] | +| file://:0:0:0:0 | [post] self [v3] | semmle.label | [post] self [v3] | | file://:0:0:0:0 | [post] self [x, some:0] | semmle.label | [post] self [x, some:0] | | file://:0:0:0:0 | [post] self [x] | semmle.label | [post] self [x] | | file://:0:0:0:0 | self [a, x] | semmle.label | self [a, x] | | file://:0:0:0:0 | self [str] | semmle.label | self [str] | +| file://:0:0:0:0 | self [v2, some:0] | semmle.label | self [v2, some:0] | +| file://:0:0:0:0 | self [v2] | semmle.label | self [v2] | +| file://:0:0:0:0 | self [v3] | semmle.label | self [v3] | | file://:0:0:0:0 | self [x, some:0] | semmle.label | self [x, some:0] | | file://:0:0:0:0 | self [x] | semmle.label | self [x] | | file://:0:0:0:0 | value | semmle.label | value | +| file://:0:0:0:0 | value | semmle.label | value | +| file://:0:0:0:0 | value | semmle.label | value | +| file://:0:0:0:0 | value [some:0] | semmle.label | value [some:0] | | file://:0:0:0:0 | value [some:0] | semmle.label | value [some:0] | | test.swift:6:19:6:26 | call to source() | semmle.label | call to source() | | test.swift:7:15:7:15 | t1 | semmle.label | t1 | @@ -706,6 +755,33 @@ nodes | test.swift:693:17:693:24 | call to source() | semmle.label | call to source() | | test.swift:694:15:694:15 | arr6 [Array element] | semmle.label | arr6 [Array element] | | test.swift:694:15:694:21 | ...[...] | semmle.label | ...[...] | +| test.swift:699:9:699:9 | self [v2, some:0] | semmle.label | self [v2, some:0] | +| test.swift:699:9:699:9 | self [v2] | semmle.label | self [v2] | +| test.swift:699:9:699:9 | value | semmle.label | value | +| test.swift:699:9:699:9 | value [some:0] | semmle.label | value [some:0] | +| test.swift:700:9:700:9 | self [v3] | semmle.label | self [v3] | +| test.swift:700:9:700:9 | value | semmle.label | value | +| test.swift:711:10:711:17 | call to source() | semmle.label | call to source() | +| test.swift:711:10:711:17 | call to source() [some:0] | semmle.label | call to source() [some:0] | +| test.swift:712:10:712:17 | call to source() | semmle.label | call to source() | +| test.swift:714:5:714:5 | [post] mo1 [v2, some:0] | semmle.label | [post] mo1 [v2, some:0] | +| test.swift:714:5:714:5 | [post] mo1 [v2] | semmle.label | [post] mo1 [v2] | +| test.swift:714:14:714:21 | call to source() | semmle.label | call to source() | +| test.swift:714:14:714:21 | call to source() [some:0] | semmle.label | call to source() [some:0] | +| test.swift:715:5:715:5 | [post] mo1 [v3] | semmle.label | [post] mo1 [v3] | +| test.swift:715:5:715:5 | mo1 [v2, some:0] | semmle.label | mo1 [v2, some:0] | +| test.swift:715:5:715:5 | mo1 [v2] | semmle.label | mo1 [v2] | +| test.swift:715:14:715:21 | call to source() | semmle.label | call to source() | +| test.swift:721:15:721:15 | v2 [some:0] | semmle.label | v2 [some:0] | +| test.swift:721:15:721:17 | ...! | semmle.label | ...! | +| test.swift:722:15:722:15 | v3 | semmle.label | v3 | +| test.swift:724:15:724:15 | mo1 [v2, some:0] | semmle.label | mo1 [v2, some:0] | +| test.swift:724:15:724:15 | mo1 [v2] | semmle.label | mo1 [v2] | +| test.swift:724:15:724:19 | .v2 | semmle.label | .v2 | +| test.swift:724:15:724:19 | .v2 [some:0] | semmle.label | .v2 [some:0] | +| test.swift:724:15:724:21 | ...! | semmle.label | ...! | +| test.swift:725:15:725:15 | mo1 [v3] | semmle.label | mo1 [v3] | +| test.swift:725:15:725:19 | .v3 | semmle.label | .v3 | 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 ... | @@ -747,6 +823,12 @@ subpaths | test.swift:622:18:622:18 | s [x] | test.swift:615:8:615:11 | s [x] | test.swift:615:3:617:3 | self[return] [s, x] | test.swift:622:12:622:19 | call to S2.init(s:) [s, x] | | test.swift:624:13:624:13 | s2 [s, x] | test.swift:623:11:623:17 | enter #keyPath(...) [s, x] | test.swift:623:11:623:17 | exit #keyPath(...) | test.swift:624:13:624:26 | \\...[...] | | test.swift:630:15:630:15 | array [Array element] | test.swift:629:13:629:22 | enter #keyPath(...) [Array element] | test.swift:629:13:629:22 | exit #keyPath(...) | test.swift:630:15:630:31 | \\...[...] | +| test.swift:714:14:714:21 | call to source() | test.swift:699:9:699:9 | value | file://:0:0:0:0 | [post] self [v2] | test.swift:714:5:714:5 | [post] mo1 [v2] | +| test.swift:714:14:714:21 | call to source() [some:0] | test.swift:699:9:699:9 | value [some:0] | file://:0:0:0:0 | [post] self [v2, some:0] | test.swift:714:5:714:5 | [post] mo1 [v2, some:0] | +| test.swift:715:14:715:21 | call to source() | test.swift:700:9:700:9 | value | file://:0:0:0:0 | [post] self [v3] | test.swift:715:5:715:5 | [post] mo1 [v3] | +| test.swift:724:15:724:15 | mo1 [v2, some:0] | test.swift:699:9:699:9 | self [v2, some:0] | file://:0:0:0:0 | .v2 [some:0] | test.swift:724:15:724:19 | .v2 [some:0] | +| test.swift:724:15:724:15 | mo1 [v2] | test.swift:699:9:699:9 | self [v2] | file://:0:0:0:0 | .v2 | test.swift:724:15:724:19 | .v2 | +| test.swift:725:15:725:15 | mo1 [v3] | test.swift:700:9:700:9 | self [v3] | file://:0:0:0:0 | .v3 | test.swift:725:15:725:19 | .v3 | #select | test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:7:15:7:15 | t1 | result | | test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:9:15:9:15 | t1 | result | @@ -835,3 +917,7 @@ subpaths | test.swift:678:15:678:26 | ...[...] | test.swift:676:20:676:27 | call to source() | test.swift:678:15:678:26 | ...[...] | result | | test.swift:682:15:682:27 | ...[...] | test.swift:681:21:681:28 | call to source() | test.swift:682:15:682:27 | ...[...] | result | | test.swift:694:15:694:21 | ...[...] | test.swift:693:17:693:24 | call to source() | test.swift:694:15:694:21 | ...[...] | result | +| test.swift:721:15:721:17 | ...! | test.swift:711:10:711:17 | call to source() | test.swift:721:15:721:17 | ...! | result | +| test.swift:722:15:722:15 | v3 | test.swift:712:10:712:17 | call to source() | test.swift:722:15:722:15 | v3 | result | +| test.swift:724:15:724:21 | ...! | test.swift:714:14:714:21 | call to source() | test.swift:724:15:724:21 | ...! | result | +| test.swift:725:15:725:19 | .v3 | test.swift:715:14:715:21 | call to source() | test.swift:725:15:725:19 | .v3 | result | diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected index 99e9ceb5ba8..972f5937d4e 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected @@ -811,3 +811,67 @@ | test.swift:693:5:693:5 | arr6 | test.swift:693:5:693:5 | &... | | test.swift:694:15:694:15 | [post] arr6 | test.swift:694:15:694:15 | &... | | test.swift:694:15:694:15 | arr6 | test.swift:694:15:694:15 | &... | +| test.swift:697:8:697:8 | SSA def(self) | test.swift:697:8:697:8 | self[return] | +| test.swift:697:8:697:8 | self | test.swift:697:8:697:8 | SSA def(self) | +| test.swift:698:9:698:9 | self | test.swift:698:9:698:9 | SSA def(self) | +| test.swift:698:9:698:9 | self | test.swift:698:9:698:9 | SSA def(self) | +| test.swift:698:9:698:9 | self | test.swift:698:9:698:9 | SSA def(self) | +| test.swift:698:9:698:9 | value | test.swift:698:9:698:9 | SSA def(value) | +| test.swift:699:9:699:9 | self | test.swift:699:9:699:9 | SSA def(self) | +| test.swift:699:9:699:9 | self | test.swift:699:9:699:9 | SSA def(self) | +| test.swift:699:9:699:9 | self | test.swift:699:9:699:9 | SSA def(self) | +| test.swift:699:9:699:9 | value | test.swift:699:9:699:9 | SSA def(value) | +| test.swift:700:9:700:9 | self | test.swift:700:9:700:9 | SSA def(self) | +| test.swift:700:9:700:9 | self | test.swift:700:9:700:9 | SSA def(self) | +| test.swift:700:9:700:9 | self | test.swift:700:9:700:9 | SSA def(self) | +| test.swift:700:9:700:9 | value | test.swift:700:9:700:9 | SSA def(value) | +| test.swift:704:9:704:9 | SSA def(v1) | test.swift:710:5:710:5 | v1 | +| test.swift:704:9:704:9 | v1 | test.swift:704:9:704:9 | SSA def(v1) | +| test.swift:704:9:704:17 | ... as ... | test.swift:704:9:704:9 | v1 | +| test.swift:704:21:704:21 | 0 | test.swift:704:9:704:17 | ... as ... | +| test.swift:705:9:705:17 | ... as ... | test.swift:705:9:705:9 | v2 | +| test.swift:705:21:705:21 | 0 | test.swift:705:9:705:17 | ... as ... | +| test.swift:706:9:706:17 | ... as ... | test.swift:706:9:706:9 | v3 | +| test.swift:706:21:706:21 | 0 | test.swift:706:9:706:17 | ... as ... | +| test.swift:707:9:707:9 | SSA def(mo1) | test.swift:713:5:713:5 | mo1 | +| test.swift:707:9:707:9 | mo1 | test.swift:707:9:707:9 | SSA def(mo1) | +| test.swift:707:15:707:27 | call to MyOptionals.init() | test.swift:707:9:707:9 | mo1 | +| test.swift:708:9:708:9 | SSA def(mo2) | test.swift:716:5:716:5 | mo2 | +| test.swift:708:9:708:9 | mo2 | test.swift:708:9:708:9 | SSA def(mo2) | +| test.swift:708:9:708:26 | ... as ... | test.swift:708:9:708:9 | mo2 | +| test.swift:708:30:708:42 | call to MyOptionals.init() | test.swift:708:9:708:26 | ... as ... | +| test.swift:710:5:710:5 | v1 | test.swift:710:5:710:7 | ...! | +| test.swift:710:5:710:5 | v1 | test.swift:720:15:720:15 | v1 | +| test.swift:711:5:711:17 | SSA def(v2) | test.swift:721:15:721:15 | v2 | +| test.swift:711:10:711:17 | call to source() | test.swift:711:5:711:17 | SSA def(v2) | +| test.swift:712:5:712:17 | SSA def(v3) | test.swift:722:15:722:15 | v3 | +| test.swift:712:10:712:17 | call to source() | test.swift:712:5:712:17 | SSA def(v3) | +| test.swift:713:5:713:5 | [post] mo1 | test.swift:714:5:714:5 | mo1 | +| test.swift:713:5:713:5 | mo1 | test.swift:714:5:714:5 | mo1 | +| test.swift:713:5:713:9 | .v1 | test.swift:713:5:713:11 | ...! | +| test.swift:714:5:714:5 | [post] mo1 | test.swift:715:5:715:5 | mo1 | +| test.swift:714:5:714:5 | mo1 | test.swift:715:5:715:5 | mo1 | +| test.swift:715:5:715:5 | [post] mo1 | test.swift:723:15:723:15 | mo1 | +| test.swift:715:5:715:5 | mo1 | test.swift:723:15:723:15 | mo1 | +| test.swift:716:5:716:5 | mo2 | test.swift:716:5:716:8 | ...! | +| test.swift:716:5:716:5 | mo2 | test.swift:717:5:717:5 | mo2 | +| test.swift:716:5:716:10 | .v1 | test.swift:716:5:716:12 | ...! | +| test.swift:717:5:717:5 | mo2 | test.swift:717:5:717:8 | ...! | +| test.swift:717:5:717:5 | mo2 | test.swift:718:5:718:5 | mo2 | +| test.swift:718:5:718:5 | mo2 | test.swift:718:5:718:8 | ...! | +| test.swift:718:5:718:5 | mo2 | test.swift:726:15:726:15 | mo2 | +| test.swift:720:15:720:15 | v1 | test.swift:720:15:720:17 | ...! | +| test.swift:721:15:721:15 | v2 | test.swift:721:15:721:17 | ...! | +| test.swift:723:15:723:15 | [post] mo1 | test.swift:724:15:724:15 | mo1 | +| test.swift:723:15:723:15 | mo1 | test.swift:724:15:724:15 | mo1 | +| test.swift:723:15:723:19 | .v1 | test.swift:723:15:723:21 | ...! | +| test.swift:724:15:724:15 | [post] mo1 | test.swift:725:15:725:15 | mo1 | +| test.swift:724:15:724:15 | mo1 | test.swift:725:15:725:15 | mo1 | +| test.swift:724:15:724:19 | .v2 | test.swift:724:15:724:21 | ...! | +| test.swift:726:15:726:15 | mo2 | test.swift:726:15:726:18 | ...! | +| test.swift:726:15:726:15 | mo2 | test.swift:727:15:727:15 | mo2 | +| test.swift:726:15:726:20 | .v1 | test.swift:726:15:726:22 | ...! | +| test.swift:727:15:727:15 | mo2 | test.swift:727:15:727:18 | ...! | +| test.swift:727:15:727:15 | mo2 | test.swift:728:15:728:15 | mo2 | +| test.swift:727:15:727:20 | .v2 | test.swift:727:15:727:22 | ...! | +| test.swift:728:15:728:15 | mo2 | test.swift:728:15:728:18 | ...! | diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift index e789964a54f..bb646d2e7dc 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift +++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift @@ -693,3 +693,37 @@ func testArray() { arr6.insert(source(), at: 2) sink(arg: arr6[0]) // $ flow=693 } + +struct MyOptionals { + var v1 : Int? = 0 + var v2 : Int? = 0 + var v3 : Int! = 0 +} + +func testWriteOptional() { + var v1 : Int? = 0 + var v2 : Int? = 0 + var v3 : Int! = 0 + var mo1 = MyOptionals() + var mo2 : MyOptionals! = MyOptionals() + + v1! = source() + v2 = source() + v3 = source() + mo1.v1! = source() + mo1.v2 = source() + mo1.v3 = source() + mo2!.v1! = source() + mo2!.v2 = source() + mo2!.v3 = source() + + sink(arg: v1!) // $ MISSING:flow=710 + sink(arg: v2!) // $ flow=711 + sink(arg: v3) // $ flow=712 + sink(arg: mo1.v1!) // $ MISSING:flow=713 + sink(arg: mo1.v2!) // $ flow=714 + sink(arg: mo1.v3) // $ flow=715 + sink(arg: mo2!.v1!) // $ MISSING:flow=716 + sink(arg: mo2!.v2!) // $ MISSING:flow=717 + sink(arg: mo2!.v3) // $ MISSING:flow=718 +} From ab3f3d03c59011afcbd4cd3d56c5abc49bf5e1db Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 4 Aug 2023 21:00:41 +0100 Subject: [PATCH 2/4] Swift: Model taint into optionals via ForceValueExpr. --- .../codeql/swift/dataflow/internal/DataFlowPrivate.qll | 8 ++++++++ .../library-tests/dataflow/dataflow/DataFlow.expected | 8 ++++++++ swift/ql/test/library-tests/dataflow/dataflow/test.swift | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index 02b32270a88..68fc8e0af59 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -702,6 +702,14 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { init.isFailable() ) or + // assignment to an optional via `!`, e.g. `optional! = ...` + exists(ForceValueExpr fve, AssignExpr assign | + fve = assign.getDest() and + node1.asExpr() = assign.getSource() and + node2.asExpr() = fve.getSubExpr() and + c instanceof OptionalSomeContentSet + ) + or // creation of an array `[v1,v2]` exists(ArrayExpr arr | node1.asExpr() = arr.getAnElement() and diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected index eb4b787609d..e60933a96a2 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected @@ -348,6 +348,8 @@ edges | test.swift:699:9:699:9 | value [some:0] | file://:0:0:0:0 | value [some:0] | | test.swift:700:9:700:9 | self [v3] | file://:0:0:0:0 | self [v3] | | test.swift:700:9:700:9 | value | file://:0:0:0:0 | value | +| test.swift:710:5:710:5 | v1 [some:0] | test.swift:720:15:720:15 | v1 [some:0] | +| test.swift:710:11:710:18 | call to source() | test.swift:710:5:710:5 | v1 [some:0] | | test.swift:711:10:711:17 | call to source() | test.swift:711:10:711:17 | call to source() [some:0] | | test.swift:711:10:711:17 | call to source() | test.swift:721:15:721:17 | ...! | | test.swift:711:10:711:17 | call to source() [some:0] | test.swift:721:15:721:15 | v2 [some:0] | @@ -364,6 +366,7 @@ edges | test.swift:715:5:715:5 | mo1 [v2] | test.swift:724:15:724:15 | mo1 [v2] | | test.swift:715:14:715:21 | call to source() | test.swift:700:9:700:9 | value | | test.swift:715:14:715:21 | call to source() | test.swift:715:5:715:5 | [post] mo1 [v3] | +| test.swift:720:15:720:15 | v1 [some:0] | test.swift:720:15:720:17 | ...! | | test.swift:721:15:721:15 | v2 [some:0] | test.swift:721:15:721:17 | ...! | | test.swift:724:15:724:15 | mo1 [v2, some:0] | test.swift:699:9:699:9 | self [v2, some:0] | | test.swift:724:15:724:15 | mo1 [v2, some:0] | test.swift:724:15:724:19 | .v2 [some:0] | @@ -761,6 +764,8 @@ nodes | test.swift:699:9:699:9 | value [some:0] | semmle.label | value [some:0] | | test.swift:700:9:700:9 | self [v3] | semmle.label | self [v3] | | test.swift:700:9:700:9 | value | semmle.label | value | +| test.swift:710:5:710:5 | v1 [some:0] | semmle.label | v1 [some:0] | +| test.swift:710:11:710:18 | call to source() | semmle.label | call to source() | | test.swift:711:10:711:17 | call to source() | semmle.label | call to source() | | test.swift:711:10:711:17 | call to source() [some:0] | semmle.label | call to source() [some:0] | | test.swift:712:10:712:17 | call to source() | semmle.label | call to source() | @@ -772,6 +777,8 @@ nodes | test.swift:715:5:715:5 | mo1 [v2, some:0] | semmle.label | mo1 [v2, some:0] | | test.swift:715:5:715:5 | mo1 [v2] | semmle.label | mo1 [v2] | | test.swift:715:14:715:21 | call to source() | semmle.label | call to source() | +| test.swift:720:15:720:15 | v1 [some:0] | semmle.label | v1 [some:0] | +| test.swift:720:15:720:17 | ...! | semmle.label | ...! | | test.swift:721:15:721:15 | v2 [some:0] | semmle.label | v2 [some:0] | | test.swift:721:15:721:17 | ...! | semmle.label | ...! | | test.swift:722:15:722:15 | v3 | semmle.label | v3 | @@ -917,6 +924,7 @@ subpaths | test.swift:678:15:678:26 | ...[...] | test.swift:676:20:676:27 | call to source() | test.swift:678:15:678:26 | ...[...] | result | | test.swift:682:15:682:27 | ...[...] | test.swift:681:21:681:28 | call to source() | test.swift:682:15:682:27 | ...[...] | result | | test.swift:694:15:694:21 | ...[...] | test.swift:693:17:693:24 | call to source() | test.swift:694:15:694:21 | ...[...] | result | +| test.swift:720:15:720:17 | ...! | test.swift:710:11:710:18 | call to source() | test.swift:720:15:720:17 | ...! | result | | test.swift:721:15:721:17 | ...! | test.swift:711:10:711:17 | call to source() | test.swift:721:15:721:17 | ...! | result | | test.swift:722:15:722:15 | v3 | test.swift:712:10:712:17 | call to source() | test.swift:722:15:722:15 | v3 | result | | test.swift:724:15:724:21 | ...! | test.swift:714:14:714:21 | call to source() | test.swift:724:15:724:21 | ...! | result | diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift index bb646d2e7dc..38e912ceb97 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift +++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift @@ -717,7 +717,7 @@ func testWriteOptional() { mo2!.v2 = source() mo2!.v3 = source() - sink(arg: v1!) // $ MISSING:flow=710 + sink(arg: v1!) // $ flow=710 sink(arg: v2!) // $ flow=711 sink(arg: v3) // $ flow=712 sink(arg: mo1.v1!) // $ MISSING:flow=713 From dc98dec5b6a8b72b09bfd88f43d83187b8d35549 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 7 Aug 2023 13:16:00 +0100 Subject: [PATCH 3/4] Swift: Change note. --- swift/ql/lib/change-notes/2023-08-07-forced-unwrap copy.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 swift/ql/lib/change-notes/2023-08-07-forced-unwrap copy.md diff --git a/swift/ql/lib/change-notes/2023-08-07-forced-unwrap copy.md b/swift/ql/lib/change-notes/2023-08-07-forced-unwrap copy.md new file mode 100644 index 00000000000..1eb9bc53012 --- /dev/null +++ b/swift/ql/lib/change-notes/2023-08-07-forced-unwrap copy.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- + +* Flow through forced optional unwrapping (`!`) on the left side of assignment now works in most cases. From 2b0fcab1823bd294b55f1be216415829656c1585 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 8 Aug 2023 16:06:52 +0100 Subject: [PATCH 4/4] Swift: Update test annotations following merge. --- .../dataflow/dataflow/DataFlowInline.expected | 10 ---------- .../library-tests/dataflow/dataflow/test.swift | 18 +++++++++--------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlowInline.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlowInline.expected index 02d2963e7d2..48de9172b36 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlowInline.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlowInline.expected @@ -1,12 +1,2 @@ failures testFailures -| test.swift:733:15:733:17 | ...! | Unexpected result: flow=723 | -| test.swift:733:20:734:1 | // $ flow=710\n | Missing result:flow=710 | -| test.swift:734:15:734:17 | ...! | Unexpected result: flow=724 | -| test.swift:734:20:735:1 | // $ flow=711\n | Missing result:flow=711 | -| test.swift:735:15:735:15 | v3 | Unexpected result: flow=725 | -| test.swift:735:19:736:1 | // $ flow=712\n | Missing result:flow=712 | -| test.swift:737:15:737:21 | ...! | Unexpected result: flow=727 | -| test.swift:737:24:738:1 | // $ flow=714\n | Missing result:flow=714 | -| test.swift:738:15:738:19 | .v3 | Unexpected result: flow=728 | -| test.swift:738:23:739:1 | // $ flow=715\n | Missing result:flow=715 | diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift index fa07ccf7207..2d738e14c94 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift +++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift @@ -730,13 +730,13 @@ func testWriteOptional() { mo2!.v2 = source() mo2!.v3 = source() - sink(arg: v1!) // $ flow=710 - sink(arg: v2!) // $ flow=711 - sink(arg: v3) // $ flow=712 - sink(arg: mo1.v1!) // $ MISSING:flow=713 - sink(arg: mo1.v2!) // $ flow=714 - sink(arg: mo1.v3) // $ flow=715 - sink(arg: mo2!.v1!) // $ MISSING:flow=716 - sink(arg: mo2!.v2!) // $ MISSING:flow=717 - sink(arg: mo2!.v3) // $ MISSING:flow=718 + sink(arg: v1!) // $ flow=723 + sink(arg: v2!) // $ flow=724 + sink(arg: v3) // $ flow=725 + sink(arg: mo1.v1!) // $ MISSING:flow=726 + sink(arg: mo1.v2!) // $ flow=727 + sink(arg: mo1.v3) // $ flow=728 + sink(arg: mo2!.v1!) // $ MISSING:flow=729 + sink(arg: mo2!.v2!) // $ MISSING:flow=730 + sink(arg: mo2!.v3) // $ MISSING:flow=731 }