Skip to content

Commit 169326f

Browse files
committed
Swift: support array keypath reads in dataflow
1 parent 0b35be2 commit 169326f

File tree

3 files changed

+23
-5
lines changed

3 files changed

+23
-5
lines changed

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -757,10 +757,13 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
757757
)
758758
or
759759
// read of a component in a key-path expression chain
760-
exists(KeyPathComponent component, FieldDecl f |
760+
exists(KeyPathComponent component|
761761
component = node1.(KeyPathComponentNodeImpl).getComponent() and
762-
f = component.getDeclRef() and
763-
c.isSingleton(any(Content::FieldContent ct | ct.getField() = f))
762+
(
763+
c.isSingleton(any(Content::FieldContent ct | ct.getField() = component.getDeclRef()))
764+
or
765+
c.isSingleton(any(Content::ArrayContent ac))
766+
)
764767
|
765768
// the next node is either the next element in the chain
766769
node2.(KeyPathComponentNodeImpl).getComponent() = component.getNextComponent()

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ edges
269269
| test.swift:592:17:592:17 | KeyPathComponent [x] | test.swift:592:11:592:17 | exit #keyPath(...) |
270270
| test.swift:593:13:593:13 | s2 [s, x] | test.swift:592:11:592:17 | enter #keyPath(...) [s, x] |
271271
| test.swift:593:13:593:13 | s2 [s, x] | test.swift:593:13:593:26 | \\...[...] |
272+
| test.swift:597:17:597:26 | [...] [Array element] | test.swift:599:15:599:15 | array [Array element] |
273+
| test.swift:597:18:597:25 | call to source() | test.swift:597:17:597:26 | [...] [Array element] |
274+
| test.swift:598:13:598:22 | enter #keyPath(...) [Array element] | test.swift:598:20:598:22 | KeyPathComponent [Array element] |
275+
| test.swift:598:20:598:22 | KeyPathComponent [Array element] | test.swift:598:13:598:22 | exit #keyPath(...) |
276+
| test.swift:599:15:599:15 | array [Array element] | test.swift:598:13:598:22 | enter #keyPath(...) [Array element] |
277+
| test.swift:599:15:599:15 | array [Array element] | test.swift:599:15:599:31 | \\...[...] |
272278
| test.swift:618:13:618:20 | call to source() | test.swift:626:15:626:15 | y |
273279
| test.swift:628:9:628:16 | call to source() | test.swift:630:10:630:11 | &... |
274280
| test.swift:628:9:628:16 | call to source() | test.swift:631:15:631:15 | x |
@@ -579,6 +585,13 @@ nodes
579585
| test.swift:592:17:592:17 | KeyPathComponent [x] | semmle.label | KeyPathComponent [x] |
580586
| test.swift:593:13:593:13 | s2 [s, x] | semmle.label | s2 [s, x] |
581587
| test.swift:593:13:593:26 | \\...[...] | semmle.label | \\...[...] |
588+
| test.swift:597:17:597:26 | [...] [Array element] | semmle.label | [...] [Array element] |
589+
| test.swift:597:18:597:25 | call to source() | semmle.label | call to source() |
590+
| test.swift:598:13:598:22 | enter #keyPath(...) [Array element] | semmle.label | enter #keyPath(...) [Array element] |
591+
| test.swift:598:13:598:22 | exit #keyPath(...) | semmle.label | exit #keyPath(...) |
592+
| test.swift:598:20:598:22 | KeyPathComponent [Array element] | semmle.label | KeyPathComponent [Array element] |
593+
| test.swift:599:15:599:15 | array [Array element] | semmle.label | array [Array element] |
594+
| test.swift:599:15:599:31 | \\...[...] | semmle.label | \\...[...] |
582595
| test.swift:618:13:618:20 | call to source() | semmle.label | call to source() |
583596
| test.swift:626:15:626:15 | y | semmle.label | y |
584597
| test.swift:628:9:628:16 | call to source() | semmle.label | call to source() |
@@ -639,6 +652,7 @@ subpaths
639652
| test.swift:590:16:590:23 | call to source() | test.swift:567:8:567:11 | x | test.swift:567:3:569:3 | self[return] [x] | test.swift:590:11:590:24 | call to S.init(x:) [x] |
640653
| test.swift:591:18:591:18 | s [x] | test.swift:584:8:584:11 | s [x] | test.swift:584:3:586:3 | self[return] [s, x] | test.swift:591:12:591:19 | call to S2.init(s:) [s, x] |
641654
| test.swift:593:13:593:13 | s2 [s, x] | test.swift:592:11:592:17 | enter #keyPath(...) [s, x] | test.swift:592:11:592:17 | exit #keyPath(...) | test.swift:593:13:593:26 | \\...[...] |
655+
| test.swift:599:15:599:15 | array [Array element] | test.swift:598:13:598:22 | enter #keyPath(...) [Array element] | test.swift:598:13:598:22 | exit #keyPath(...) | test.swift:599:15:599:31 | \\...[...] |
642656
#select
643657
| test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:7:15:7:15 | t1 | result |
644658
| test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() | test.swift:9:15:9:15 | t1 | result |
@@ -712,6 +726,7 @@ subpaths
712726
| test.swift:575:13:575:25 | \\...[...] | test.swift:573:16:573:23 | call to source() | test.swift:575:13:575:25 | \\...[...] | result |
713727
| test.swift:578:13:578:32 | \\...[...] | test.swift:573:16:573:23 | call to source() | test.swift:578:13:578:32 | \\...[...] | result |
714728
| test.swift:593:13:593:26 | \\...[...] | test.swift:590:16:590:23 | call to source() | test.swift:593:13:593:26 | \\...[...] | result |
729+
| test.swift:599:15:599:31 | \\...[...] | test.swift:597:18:597:25 | call to source() | test.swift:599:15:599:31 | \\...[...] | result |
715730
| test.swift:626:15:626:15 | y | test.swift:618:13:618:20 | call to source() | test.swift:626:15:626:15 | y | result |
716731
| test.swift:631:15:631:15 | x | test.swift:628:9:628:16 | call to source() | test.swift:631:15:631:15 | x | result |
717732
| test.swift:632:15:632:15 | y | test.swift:628:9:628:16 | call to source() | test.swift:632:15:632:15 | y | result |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ func testNestedKeyPath() {
596596
func testArrayKeyPath() {
597597
let array = [source()]
598598
let f = \[Int].[0]
599-
sink(arg: array[keyPath: f]) // $ MISSING: flow=597
599+
sink(arg: array[keyPath: f]) // $ flow=597
600600
}
601601

602602
struct S2_Optional {
@@ -656,5 +656,5 @@ func testArray() {
656656

657657
var arr6 = [1,2,3]
658658
arr6.insert(source(), at: 2)
659-
sink(arg: arr6)
659+
sink(arg: arr6) // $ MISSING: flow=658
660660
}

0 commit comments

Comments
 (0)