Skip to content

Commit 2f6f376

Browse files
authored
Merge pull request #15230 from geoffw0/swiftui
Swift: Add dataflow tests for property wrappers and SwiftUI
2 parents c84e85d + 4016033 commit 2f6f376

File tree

5 files changed

+361
-0
lines changed

5 files changed

+361
-0
lines changed

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,29 @@
11
edges
2+
| file://:0:0:0:0 | .wrappedValue | test.swift:949:15:949:15 | x |
3+
| file://:0:0:0:0 | .wrappedValue | test.swift:951:15:951:15 | x |
24
| file://:0:0:0:0 | KeyPathComponent [some:0] | test.swift:663:13:663:29 | exit #keyPath(...) [some:0] |
5+
| file://:0:0:0:0 | [post] self [wrappedValue] | file://:0:0:0:0 | self [wrappedValue] |
36
| file://:0:0:0:0 | self [a, x] | file://:0:0:0:0 | .a [x] |
47
| file://:0:0:0:0 | self [s, x] | file://:0:0:0:0 | .s [x] |
58
| file://:0:0:0:0 | self [str] | file://:0:0:0:0 | .str |
69
| file://:0:0:0:0 | self [v2, some:0] | file://:0:0:0:0 | .v2 [some:0] |
710
| file://:0:0:0:0 | self [v2] | file://:0:0:0:0 | .v2 |
811
| file://:0:0:0:0 | self [v3] | file://:0:0:0:0 | .v3 |
912
| file://:0:0:0:0 | self [v] | file://:0:0:0:0 | .v |
13+
| file://:0:0:0:0 | self [wrappedValue] | test.swift:958:9:958:9 | self [wrappedValue] |
1014
| file://:0:0:0:0 | self [x, some:0] | file://:0:0:0:0 | .x [some:0] |
1115
| file://:0:0:0:0 | self [x] | file://:0:0:0:0 | .x |
1216
| file://:0:0:0:0 | self [x] | file://:0:0:0:0 | .x |
1317
| file://:0:0:0:0 | self [x] | file://:0:0:0:0 | .x |
1418
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v2] |
1519
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v3] |
1620
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [v] |
21+
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [wrappedValue] |
1722
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [x] |
1823
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [x] |
24+
| file://:0:0:0:0 | value | test.swift:938:9:938:9 | newValue |
25+
| file://:0:0:0:0 | value | test.swift:957:9:957:9 | value |
26+
| file://:0:0:0:0 | value | test.swift:965:9:965:9 | newValue |
1927
| file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [v2, some:0] |
2028
| file://:0:0:0:0 | value [some:0] | file://:0:0:0:0 | [post] self [x, some:0] |
2129
| test.swift:6:19:6:26 | call to source() | test.swift:7:15:7:15 | t1 |
@@ -606,6 +614,24 @@ edges
606614
| test.swift:908:19:908:26 | call to source() | test.swift:904:13:904:18 | call to ... |
607615
| test.swift:927:12:927:31 | call to source(_:) | test.swift:927:12:927:31 | OpenExistentialExpr |
608616
| test.swift:929:12:929:57 | call to source(_:) | test.swift:929:12:929:57 | OpenExistentialExpr |
617+
| test.swift:937:22:937:29 | call to source() | file://:0:0:0:0 | .wrappedValue |
618+
| test.swift:938:9:938:9 | newValue | test.swift:938:25:938:25 | newValue |
619+
| test.swift:941:10:941:24 | wrappedValue | test.swift:942:19:942:19 | wrappedValue |
620+
| test.swift:943:29:943:36 | call to source() | test.swift:938:9:938:9 | newValue |
621+
| test.swift:948:33:948:33 | value | file://:0:0:0:0 | value |
622+
| test.swift:948:42:948:49 | call to source() | test.swift:941:10:941:24 | wrappedValue |
623+
| test.swift:950:9:950:16 | call to source() | test.swift:948:33:948:33 | value |
624+
| test.swift:957:9:957:9 | value | file://:0:0:0:0 | value |
625+
| test.swift:958:9:958:9 | self [wrappedValue] | test.swift:959:23:959:23 | self [wrappedValue] |
626+
| test.swift:959:23:959:23 | self [wrappedValue] | test.swift:959:23:959:23 | .wrappedValue |
627+
| test.swift:965:9:965:9 | newValue | test.swift:967:28:967:28 | newValue |
628+
| test.swift:967:28:967:28 | newValue | test.swift:957:9:957:9 | value |
629+
| test.swift:971:10:971:24 | wrappedValue | test.swift:972:19:972:19 | wrappedValue |
630+
| test.swift:978:34:978:34 | value | file://:0:0:0:0 | value |
631+
| test.swift:980:9:980:16 | call to source() | test.swift:978:34:978:34 | value |
632+
| test.swift:983:38:983:45 | call to source() | test.swift:971:10:971:24 | wrappedValue |
633+
| test.swift:988:34:988:34 | value | file://:0:0:0:0 | value |
634+
| test.swift:991:10:991:17 | call to source() | test.swift:988:34:988:34 | value |
609635
nodes
610636
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
611637
| file://:0:0:0:0 | .s [x] | semmle.label | .s [x] |
@@ -614,6 +640,7 @@ nodes
614640
| file://:0:0:0:0 | .v2 | semmle.label | .v2 |
615641
| file://:0:0:0:0 | .v2 [some:0] | semmle.label | .v2 [some:0] |
616642
| file://:0:0:0:0 | .v3 | semmle.label | .v3 |
643+
| file://:0:0:0:0 | .wrappedValue | semmle.label | .wrappedValue |
617644
| file://:0:0:0:0 | .x | semmle.label | .x |
618645
| file://:0:0:0:0 | .x | semmle.label | .x |
619646
| file://:0:0:0:0 | .x | semmle.label | .x |
@@ -623,6 +650,7 @@ nodes
623650
| file://:0:0:0:0 | [post] self [v2] | semmle.label | [post] self [v2] |
624651
| file://:0:0:0:0 | [post] self [v3] | semmle.label | [post] self [v3] |
625652
| file://:0:0:0:0 | [post] self [v] | semmle.label | [post] self [v] |
653+
| file://:0:0:0:0 | [post] self [wrappedValue] | semmle.label | [post] self [wrappedValue] |
626654
| file://:0:0:0:0 | [post] self [x, some:0] | semmle.label | [post] self [x, some:0] |
627655
| file://:0:0:0:0 | [post] self [x] | semmle.label | [post] self [x] |
628656
| file://:0:0:0:0 | [post] self [x] | semmle.label | [post] self [x] |
@@ -633,6 +661,7 @@ nodes
633661
| file://:0:0:0:0 | self [v2] | semmle.label | self [v2] |
634662
| file://:0:0:0:0 | self [v3] | semmle.label | self [v3] |
635663
| file://:0:0:0:0 | self [v] | semmle.label | self [v] |
664+
| file://:0:0:0:0 | self [wrappedValue] | semmle.label | self [wrappedValue] |
636665
| file://:0:0:0:0 | self [x, some:0] | semmle.label | self [x, some:0] |
637666
| file://:0:0:0:0 | self [x] | semmle.label | self [x] |
638667
| file://:0:0:0:0 | self [x] | semmle.label | self [x] |
@@ -642,6 +671,10 @@ nodes
642671
| file://:0:0:0:0 | value | semmle.label | value |
643672
| file://:0:0:0:0 | value | semmle.label | value |
644673
| file://:0:0:0:0 | value | semmle.label | value |
674+
| file://:0:0:0:0 | value | semmle.label | value |
675+
| file://:0:0:0:0 | value | semmle.label | value |
676+
| file://:0:0:0:0 | value | semmle.label | value |
677+
| file://:0:0:0:0 | value | semmle.label | value |
645678
| file://:0:0:0:0 | value [some:0] | semmle.label | value [some:0] |
646679
| file://:0:0:0:0 | value [some:0] | semmle.label | value [some:0] |
647680
| test.swift:6:19:6:26 | call to source() | semmle.label | call to source() |
@@ -1262,6 +1295,30 @@ nodes
12621295
| test.swift:929:12:929:57 | OpenExistentialExpr | semmle.label | OpenExistentialExpr |
12631296
| test.swift:929:12:929:57 | call to source(_:) | semmle.label | call to source(_:) |
12641297
| test.swift:930:12:930:65 | call to source(_:) | semmle.label | call to source(_:) |
1298+
| test.swift:937:22:937:29 | call to source() | semmle.label | call to source() |
1299+
| test.swift:938:9:938:9 | newValue | semmle.label | newValue |
1300+
| test.swift:938:25:938:25 | newValue | semmle.label | newValue |
1301+
| test.swift:941:10:941:24 | wrappedValue | semmle.label | wrappedValue |
1302+
| test.swift:942:19:942:19 | wrappedValue | semmle.label | wrappedValue |
1303+
| test.swift:943:29:943:36 | call to source() | semmle.label | call to source() |
1304+
| test.swift:948:33:948:33 | value | semmle.label | value |
1305+
| test.swift:948:42:948:49 | call to source() | semmle.label | call to source() |
1306+
| test.swift:949:15:949:15 | x | semmle.label | x |
1307+
| test.swift:950:9:950:16 | call to source() | semmle.label | call to source() |
1308+
| test.swift:951:15:951:15 | x | semmle.label | x |
1309+
| test.swift:957:9:957:9 | value | semmle.label | value |
1310+
| test.swift:958:9:958:9 | self [wrappedValue] | semmle.label | self [wrappedValue] |
1311+
| test.swift:959:23:959:23 | .wrappedValue | semmle.label | .wrappedValue |
1312+
| test.swift:959:23:959:23 | self [wrappedValue] | semmle.label | self [wrappedValue] |
1313+
| test.swift:965:9:965:9 | newValue | semmle.label | newValue |
1314+
| test.swift:967:28:967:28 | newValue | semmle.label | newValue |
1315+
| test.swift:971:10:971:24 | wrappedValue | semmle.label | wrappedValue |
1316+
| test.swift:972:19:972:19 | wrappedValue | semmle.label | wrappedValue |
1317+
| test.swift:978:34:978:34 | value | semmle.label | value |
1318+
| test.swift:980:9:980:16 | call to source() | semmle.label | call to source() |
1319+
| test.swift:983:38:983:45 | call to source() | semmle.label | call to source() |
1320+
| test.swift:988:34:988:34 | value | semmle.label | value |
1321+
| test.swift:991:10:991:17 | call to source() | semmle.label | call to source() |
12651322
subpaths
12661323
| 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 |
12671324
| 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 ... |
@@ -1463,3 +1520,11 @@ subpaths
14631520
| test.swift:928:12:928:31 | call to source(_:) | test.swift:928:12:928:31 | call to source(_:) | test.swift:928:12:928:31 | call to source(_:) | result |
14641521
| test.swift:929:12:929:57 | OpenExistentialExpr | test.swift:929:12:929:57 | call to source(_:) | test.swift:929:12:929:57 | OpenExistentialExpr | result |
14651522
| test.swift:930:12:930:65 | call to source(_:) | test.swift:930:12:930:65 | call to source(_:) | test.swift:930:12:930:65 | call to source(_:) | result |
1523+
| test.swift:938:25:938:25 | newValue | test.swift:943:29:943:36 | call to source() | test.swift:938:25:938:25 | newValue | result |
1524+
| test.swift:938:25:938:25 | newValue | test.swift:950:9:950:16 | call to source() | test.swift:938:25:938:25 | newValue | result |
1525+
| test.swift:942:19:942:19 | wrappedValue | test.swift:948:42:948:49 | call to source() | test.swift:942:19:942:19 | wrappedValue | result |
1526+
| test.swift:949:15:949:15 | x | test.swift:937:22:937:29 | call to source() | test.swift:949:15:949:15 | x | result |
1527+
| test.swift:951:15:951:15 | x | test.swift:937:22:937:29 | call to source() | test.swift:951:15:951:15 | x | result |
1528+
| test.swift:959:23:959:23 | .wrappedValue | test.swift:980:9:980:16 | call to source() | test.swift:959:23:959:23 | .wrappedValue | result |
1529+
| test.swift:959:23:959:23 | .wrappedValue | test.swift:991:10:991:17 | call to source() | test.swift:959:23:959:23 | .wrappedValue | result |
1530+
| test.swift:972:19:972:19 | wrappedValue | test.swift:983:38:983:45 | call to source() | test.swift:972:19:972:19 | wrappedValue | result |

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,3 +1165,57 @@
11651165
| test.swift:926:45:926:48 | y | test.swift:926:45:926:48 | SSA def(y) |
11661166
| test.swift:927:12:927:31 | call to source(_:) | test.swift:927:12:927:31 | OpenExistentialExpr |
11671167
| test.swift:929:12:929:57 | call to source(_:) | test.swift:929:12:929:57 | OpenExistentialExpr |
1168+
| test.swift:936:9:936:9 | self | test.swift:936:9:936:9 | SSA def(self) |
1169+
| test.swift:937:9:937:9 | SSA def(self) | test.swift:937:9:937:31 | self[return] |
1170+
| test.swift:937:9:937:9 | self | test.swift:937:9:937:9 | SSA def(self) |
1171+
| test.swift:938:9:938:9 | SSA def(newValue) | test.swift:938:25:938:25 | newValue |
1172+
| test.swift:938:9:938:9 | SSA def(self) | test.swift:938:9:938:35 | self[return] |
1173+
| test.swift:938:9:938:9 | newValue | test.swift:938:9:938:9 | SSA def(newValue) |
1174+
| test.swift:938:9:938:9 | self | test.swift:938:9:938:9 | SSA def(self) |
1175+
| test.swift:941:5:941:5 | SSA def(self) | test.swift:943:9:943:9 | self |
1176+
| test.swift:941:5:941:5 | self | test.swift:941:5:941:5 | SSA def(self) |
1177+
| test.swift:941:10:941:24 | SSA def(wrappedValue) | test.swift:942:19:942:19 | wrappedValue |
1178+
| test.swift:941:10:941:24 | wrappedValue | test.swift:941:10:941:24 | SSA def(wrappedValue) |
1179+
| test.swift:943:9:943:9 | [post] self | test.swift:941:5:944:5 | self[return] |
1180+
| test.swift:943:9:943:9 | self | test.swift:941:5:944:5 | self[return] |
1181+
| test.swift:948:6:948:49 | call to MyTaintPropertyWrapper.init(wrappedValue:) | test.swift:948:33:948:36 | ... as ... |
1182+
| test.swift:948:33:948:33 | value | test.swift:948:33:948:33 | SSA def(value) |
1183+
| test.swift:948:33:948:36 | ... as ... | test.swift:948:33:948:33 | x |
1184+
| test.swift:957:9:957:9 | self | test.swift:957:9:957:9 | SSA def(self) |
1185+
| test.swift:957:9:957:9 | self | test.swift:957:9:957:9 | SSA def(self) |
1186+
| test.swift:957:9:957:9 | self | test.swift:957:9:957:9 | SSA def(self) |
1187+
| test.swift:957:9:957:9 | value | test.swift:957:9:957:9 | SSA def(value) |
1188+
| test.swift:958:9:958:9 | SSA def(self) | test.swift:959:23:959:23 | self |
1189+
| test.swift:958:9:958:9 | self | test.swift:958:9:958:9 | SSA def(self) |
1190+
| test.swift:959:23:959:23 | [post] self | test.swift:958:9:960:9 | self[return] |
1191+
| test.swift:959:23:959:23 | self | test.swift:958:9:960:9 | self[return] |
1192+
| test.swift:963:9:963:9 | self | test.swift:963:9:963:9 | SSA def(self) |
1193+
| test.swift:964:9:964:9 | SSA def(self) | test.swift:964:15:964:15 | self |
1194+
| test.swift:964:9:964:9 | self | test.swift:964:9:964:9 | SSA def(self) |
1195+
| test.swift:964:15:964:15 | [post] self | test.swift:964:9:964:28 | self[return] |
1196+
| test.swift:964:15:964:15 | self | test.swift:964:9:964:28 | self[return] |
1197+
| test.swift:965:9:965:9 | SSA def(newValue) | test.swift:967:28:967:28 | newValue |
1198+
| test.swift:965:9:965:9 | SSA def(self) | test.swift:966:23:966:23 | self |
1199+
| test.swift:965:9:965:9 | newValue | test.swift:965:9:965:9 | SSA def(newValue) |
1200+
| test.swift:965:9:965:9 | self | test.swift:965:9:965:9 | SSA def(self) |
1201+
| test.swift:966:23:966:23 | [post] self | test.swift:967:13:967:13 | self |
1202+
| test.swift:966:23:966:23 | self | test.swift:967:13:967:13 | self |
1203+
| test.swift:967:13:967:13 | [post] self | test.swift:965:9:968:9 | self[return] |
1204+
| test.swift:967:13:967:13 | self | test.swift:965:9:968:9 | self[return] |
1205+
| test.swift:971:5:971:5 | SSA def(self) | test.swift:973:9:973:9 | self |
1206+
| test.swift:971:5:971:5 | self | test.swift:971:5:971:5 | SSA def(self) |
1207+
| test.swift:971:10:971:24 | SSA def(wrappedValue) | test.swift:972:19:972:19 | wrappedValue |
1208+
| test.swift:971:10:971:24 | wrappedValue | test.swift:971:10:971:24 | SSA def(wrappedValue) |
1209+
| test.swift:972:19:972:19 | [post] wrappedValue | test.swift:973:29:973:29 | wrappedValue |
1210+
| test.swift:972:19:972:19 | wrappedValue | test.swift:973:29:973:29 | wrappedValue |
1211+
| test.swift:973:9:973:9 | [post] self | test.swift:971:5:974:5 | self[return] |
1212+
| test.swift:973:9:973:9 | self | test.swift:971:5:974:5 | self[return] |
1213+
| test.swift:978:6:978:38 | call to MySimplePropertyWrapper.init(wrappedValue:) | test.swift:978:34:978:34 | a |
1214+
| test.swift:978:34:978:34 | value | test.swift:978:34:978:34 | SSA def(value) |
1215+
| test.swift:978:34:978:34 | value | test.swift:978:34:978:34 | SSA def(value) |
1216+
| test.swift:983:6:983:45 | call to MySimplePropertyWrapper.init(wrappedValue:) | test.swift:983:34:983:34 | b |
1217+
| test.swift:983:34:983:34 | value | test.swift:983:34:983:34 | SSA def(value) |
1218+
| test.swift:983:34:983:34 | value | test.swift:983:34:983:34 | SSA def(value) |
1219+
| test.swift:988:6:988:38 | call to MySimplePropertyWrapper.init(wrappedValue:) | test.swift:988:34:988:34 | c |
1220+
| test.swift:988:34:988:34 | value | test.swift:988:34:988:34 | SSA def(value) |
1221+
| test.swift:988:34:988:34 | value | test.swift:988:34:988:34 | SSA def(value) |

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

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,3 +931,64 @@ func testOpenExistentialExpr(x: MyProtocol, y: MyProcotolImpl) {
931931
}
932932

933933
// ---
934+
935+
@propertyWrapper struct MyTaintPropertyWrapper {
936+
var wrappedValue: Int {
937+
get { return source() }
938+
set { sink(arg: newValue) } // $ flow=943 flow=950
939+
}
940+
941+
init(wrappedValue: Int) {
942+
sink(arg: wrappedValue) // $ flow=948
943+
self.wrappedValue = source()
944+
}
945+
}
946+
947+
func test_my_taint_property_wrapper() {
948+
@MyTaintPropertyWrapper var x: Int = source()
949+
sink(arg: x) // $ flow=937
950+
x = source()
951+
sink(arg: x) // $ flow=937
952+
}
953+
954+
// ---
955+
956+
@propertyWrapper struct MySimplePropertyWrapper {
957+
var wrappedValue: Int {
958+
didSet {
959+
sink(arg: wrappedValue) // $ flow=980 flow=991
960+
}
961+
}
962+
963+
var projectedValue: Int {
964+
get { wrappedValue }
965+
set {
966+
sink(arg: wrappedValue) // $ MISSING: flow=991
967+
wrappedValue = newValue
968+
}
969+
}
970+
971+
init(wrappedValue: Int) {
972+
sink(arg: wrappedValue) // $ flow=983
973+
self.wrappedValue = wrappedValue
974+
}
975+
}
976+
977+
func test_my_property_wrapper() {
978+
@MySimplePropertyWrapper var a = 0
979+
sink(arg: a)
980+
a = source()
981+
sink(arg: a) // $ MISSING: flow=980
982+
983+
@MySimplePropertyWrapper var b = source()
984+
sink(arg: b) // $ MISSING: flow=983
985+
b = 0
986+
sink(arg: b)
987+
988+
@MySimplePropertyWrapper var c = 0
989+
sink(arg: c)
990+
sink(arg: $c)
991+
$c = source()
992+
sink(arg: c) // $ MISSING: flow=991
993+
sink(arg: $c) // $ MISSING: flow=991
994+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
2+
// --- stubs ---
3+
4+
protocol View {
5+
}
6+
7+
struct Binding<Value> {
8+
}
9+
10+
@propertyWrapper
11+
struct State<Value> { // an @State
12+
var wrappedValue: Value
13+
var projectedValue: Binding<Value> { get { return 0 as! Binding<Value> } } // what you get with `$`
14+
}
15+
16+
struct LocalizedStringKey : ExpressibleByStringLiteral {
17+
typealias StringLiteralType = String
18+
19+
init(stringLiteral value: Self.StringLiteralType) {
20+
}
21+
}
22+
23+
struct Label<Title, Icon> : View where Title : View, Icon : View {
24+
}
25+
26+
struct Text : View {
27+
}
28+
29+
struct TextField<Label> : View where Label : View {
30+
init(_ titleKey: LocalizedStringKey, text: Binding<String>) where Label == Text { }
31+
}
32+
33+
struct SecureField<Label> : View where Label : View {
34+
init(_ titleKey: LocalizedStringKey, text: Binding<String>, prompt: Text?) where Label == Text { }
35+
}
36+
37+
struct TextEditor : View {
38+
init(text: Binding<String>) { }
39+
}
40+
41+
struct SubmitTriggers {
42+
init(rawValue: UInt) {
43+
self.rawValue = rawValue
44+
}
45+
46+
var rawValue: UInt
47+
48+
static let text = SubmitTriggers(rawValue: 1)
49+
}
50+
51+
extension View {
52+
func onSubmit(
53+
of triggers: SubmitTriggers = .text,
54+
_ action: @escaping (() -> Void)
55+
) -> some View {
56+
return self
57+
}
58+
}
59+
60+
// --- tests ---
61+
62+
func sink(arg: Any) { }
63+
64+
func mkHarmlessBinding(text: Binding<String>) { }
65+
66+
struct MyStruct {
67+
@State var input: String = "default value"
68+
@State var harmless: String = "default value"
69+
@State var harmless2: String = "default value"
70+
71+
var myView1: some View {
72+
TextField("title", text: $input)
73+
.onSubmit {
74+
sink(arg: input) // $ MISSING: tainted
75+
sink(arg: harmless)
76+
mkHarmlessBinding(text: $harmless2)
77+
sink(arg: harmless2)
78+
}
79+
}
80+
81+
@State var secureInput: String = "default value"
82+
83+
var myView2: some View {
84+
SecureField("title", text: $secureInput, prompt: nil)
85+
.onSubmit {
86+
sink(arg: secureInput) // $ MISSING: tainted
87+
}
88+
}
89+
90+
@State var longInput: String = "default value"
91+
92+
var myView3: some View {
93+
TextEditor(text: $longInput)
94+
.onSubmit {
95+
sink(arg: longInput) // $ MISSING: tainted
96+
}
97+
}
98+
}

0 commit comments

Comments
 (0)