From e1d5bd24897939d25712a33d4d0b5a0e3c6c3c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Mon, 28 Aug 2023 14:43:42 +0200 Subject: [PATCH 01/13] Swift: change note --- swift/ql/lib/change-notes/2023-08-28-shared-capture-flow.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 swift/ql/lib/change-notes/2023-08-28-shared-capture-flow.md diff --git a/swift/ql/lib/change-notes/2023-08-28-shared-capture-flow.md b/swift/ql/lib/change-notes/2023-08-28-shared-capture-flow.md new file mode 100644 index 000000000000..0620c2c7a7b8 --- /dev/null +++ b/swift/ql/lib/change-notes/2023-08-28-shared-capture-flow.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* Introduced support for flow through captured variables that properly adheres to inter-procedural control flow. From 63d6e52f3986127c0392dcd30cd838094cdf68df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Tue, 29 Aug 2023 16:47:41 +0200 Subject: [PATCH 02/13] Swift: add failing inline expectation test based on closure AST tests. --- .../ql/test/TestUtilities/InlineFlowTest.qll | 117 +++++++++++++ .../dataflow/capture/closures.swift | 155 ++++++++++++++++++ .../dataflow/capture/inlinetest.expected | 2 + .../dataflow/capture/inlinetest.ql | 2 + 4 files changed, 276 insertions(+) create mode 100644 swift/ql/test/TestUtilities/InlineFlowTest.qll create mode 100644 swift/ql/test/library-tests/dataflow/capture/closures.swift create mode 100644 swift/ql/test/library-tests/dataflow/capture/inlinetest.expected create mode 100644 swift/ql/test/library-tests/dataflow/capture/inlinetest.ql diff --git a/swift/ql/test/TestUtilities/InlineFlowTest.qll b/swift/ql/test/TestUtilities/InlineFlowTest.qll new file mode 100644 index 000000000000..4dcd1fb8bc57 --- /dev/null +++ b/swift/ql/test/TestUtilities/InlineFlowTest.qll @@ -0,0 +1,117 @@ +/** + * Provides a simple base test for flow-related tests using inline expectations. + * + * Example for a test.ql: + * ```ql + * import swift + * import TestUtilities.InlineFlowTest + * import DefaultFlowTest + * import PathGraph + * + * from PathNode source, PathNode sink + * where flowPath(source, sink) + * select sink, source, sink, "$@", source, source.toString() + * ``` + * + * To declare expectations, you can use the $hasTaintFlow or $hasValueFlow comments within the test source files. + * Example of the corresponding test file, e.g. Test.java + * ```swift + * func source() -> Any { return nil } + * func taint() -> Any { return nil } + * func sink(_ o: Any) { } + * + * func test() { + * let s = source() + * sink(s) // $ hasValueFlow + * let t = "foo" + taint() + * sink(t); // $ hasTaintFlow + * } + * ``` + * + * If you are only interested in value flow, then instead of importing `DefaultFlowTest`, you can import + * `ValueFlowTest`. Similarly, if you are only interested in taint flow, then instead of + * importing `DefaultFlowTest`, you can import `TaintFlowTest`. In both cases + * `DefaultFlowConfig` can be replaced by another implementation of `DataFlow::ConfigSig`. + * + * If you need more fine-grained tuning, consider implementing a test using `InlineExpectationsTest`. + */ + +import codeql.swift.dataflow.DataFlow +import codeql.swift.dataflow.ExternalFlow +import codeql.swift.dataflow.TaintTracking +import TestUtilities.InlineExpectationsTest + +private predicate defaultSource(DataFlow::Node source) { + source.asExpr().(MethodCallExpr).getStaticTarget().getName() = ["source", "taint"] +} + +private predicate defaultSink(DataFlow::Node sink) { + exists(MethodCallExpr ma | ma.getStaticTarget().hasName("sink") | + sink.asExpr() = ma.getAnArgument().getExpr() + ) +} + +module DefaultFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { defaultSource(source) } + + predicate isSink(DataFlow::Node sink) { defaultSink(sink) } + + int fieldFlowBranchLimit() { result = 1000 } +} + +private module NoFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { none() } + + predicate isSink(DataFlow::Node sink) { none() } +} + +private string getSourceArgString(DataFlow::Node src) { + defaultSource(src) and + src.asExpr().(MethodCallExpr).getAnArgument().getExpr().(StringLiteralExpr).getValue() = result +} + +module FlowTest { + module ValueFlow = DataFlow::Global; + + module TaintFlow = TaintTracking::Global; + + private module InlineTest implements TestSig { + string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasValueFlow" and + exists(DataFlow::Node src, DataFlow::Node sink | ValueFlow::flow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" + ) + or + tag = "hasTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink | + TaintFlow::flow(src, sink) and not ValueFlow::flow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" + ) + } + } + + import MakeTest + import DataFlow::MergePathGraph + + predicate flowPath(PathNode source, PathNode sink) { + ValueFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) or + TaintFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) + } +} + +module DefaultFlowTest = FlowTest; + +module ValueFlowTest { + import FlowTest +} + +module TaintFlowTest { + import FlowTest +} diff --git a/swift/ql/test/library-tests/dataflow/capture/closures.swift b/swift/ql/test/library-tests/dataflow/capture/closures.swift new file mode 100644 index 000000000000..8260782e129c --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/capture/closures.swift @@ -0,0 +1,155 @@ +func sink(_ value: T) { print("sink:", value) } +func source(_ label: String, _ value: T) -> T { return value } +func taint(_ label: String, _ value: T) -> T { return value } + +func hello() -> String { + let value = "Hello world!" + return source("hello", value) +} + +func captureList() { + let y: Int = source("captureList", 123); + { [x = hello()] () in + sink(x) // $ MISSING: hasValueFlow=hello + sink(y) // $ MISSING: hasValueFlow=captureList + }() +} + +var escape: (() -> Int)? = nil + +func setEscape() { + var x = source("setEscape", 0) + escape = { + sink(x) // $ MISSING: hasValueFlow=setEscape + return x + 1 + } +} + +func callEscape() { + setEscape() + sink(escape?()) // $ MISSING: hasTaintFlow=setEscape +} + +func logical() -> Bool { + let f: ((Int) -> Int)? = { x in x + 1 } + let x: Int? = source("logical", 42) + return f != nil + && (x != nil + && f!(x!) == 43) // $ MISSING: hasValueFlow=logical +} + +func asyncTest() { + func withCallback(_ callback: @escaping (Int) async -> Int) { + @Sendable + func wrapper(_ x: Int) async -> Int { + return await callback(x + 1) // $ MISSING: hasValueFlow=asyncTest + } + Task { + print("asyncTest():", await wrapper(source("asyncTest", 40))) + } + } + withCallback { x in + x + 1 // $ MISSING: hasTaintFlow=asyncTest + } +} + +func foo() -> Int { + var x = 1 + let f = { y in x += y } + x = source("foo", 41) + let r = { x } + sink(r()) // $ MISSING: hasValueFlow=foo + f(1) + return r() // $ MISSING: hasTaintFlow=foo +} + +func bar() -> () -> Int { + var x = 1 + let f = { y in x += y } + x = source("bar", 41) + let r = { x } + f(1) + return r // constantly 42 +} + +var g: ((Int) -> Void)? = nil +func baz() -> () -> Int { + var x = 1 + g = { y in x += y } + x = source("baz", 41) + let r = { x } + g!(1) + return r +} + +func sharedCapture() -> Int { + let (incrX, getX) = { + var x = source("sharedCapture", 0) + return ({ x += 1 }, { x }) + }() + + let doubleIncrX = { + incrX() + incrX() + } + + sink(getX()) // $ MISSING: hasValueFlow=sharedCapture + doubleIncrX() + sink(getX()) // $ MISSING: hasTaintFlow=sharedCapture + doubleIncrX() + return getX() +} + +func sharedCaptureMultipleWriters() { + var x = 123 + + let callSink1 = { sink(x) } // $ MISSING: hasValueFlow=setter1 + let callSink2 = { sink(x) } // $ MISSING: hasValueFlow=setter2 + + let makeSetter = { y in + let setter = { x = y } + return setter + } + + let setter1 = makeSetter(source("setter1", 1)) + let setter2 = makeSetter(source("setter2", 2)) + + setter1() + callSink1() + + setter2() + callSink2() +} + + +func main() { + print("captureList():") + captureList() // Hello world! 123 + + print("callEscape():") + callEscape() // 1 + + print("logical():", logical()) // true + + print("asyncTest():") + asyncTest() // 42 + + print("foo():", foo()) // 42 + + let a = bar() + let b = baz() + + print("bar():", a(), a()) // $ MISSING: hasTaintFlow=bar + + print("baz():", b(), b()) // $ MISSING: hasTaintFlow=baz + + g!(1) + print("g!(1):", b(), b()) // $ MISSING: hasTaintFlow=baz + + print("sharedCapture():", sharedCapture()) // 4 + + print("sharedCaptureMultipleWriters():") + sharedCaptureMultipleWriters() // 42, -1 +} + +main() diff --git a/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected b/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected new file mode 100644 index 000000000000..48de9172b362 --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/capture/inlinetest.expected @@ -0,0 +1,2 @@ +failures +testFailures diff --git a/swift/ql/test/library-tests/dataflow/capture/inlinetest.ql b/swift/ql/test/library-tests/dataflow/capture/inlinetest.ql new file mode 100644 index 000000000000..50e3f8d2f7de --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/capture/inlinetest.ql @@ -0,0 +1,2 @@ +import TestUtilities.InlineFlowTest +import DefaultFlowTest From 6296a8b3f6e388cd6e9ff5fb6d01c1aea1b0eb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Tue, 29 Aug 2023 17:04:44 +0200 Subject: [PATCH 03/13] Swift: add partial flow test starting from all sources in the test file. --- .../dataflow/capture/partialflowtest.expected | 156 ++++++++++++++++++ .../dataflow/capture/partialflowtest.ql | 32 ++++ 2 files changed, 188 insertions(+) create mode 100644 swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected create mode 100644 swift/ql/test/library-tests/dataflow/capture/partialflowtest.ql diff --git a/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected b/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected new file mode 100644 index 000000000000..86ab8a7c05a1 --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected @@ -0,0 +1,156 @@ +| closures.swift:7:17:7:17 | hello | closures.swift:2:16:2:25 | label | +| closures.swift:7:17:7:17 | hello | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:7:17:7:17 | hello | closures.swift:2:33:2:42 | value | +| closures.swift:7:17:7:17 | hello | closures.swift:2:59:2:59 | value | +| closures.swift:7:17:7:17 | hello | closures.swift:7:10:7:31 | call to source(_:_:) | +| closures.swift:7:17:7:17 | hello | closures.swift:7:26:7:26 | value | +| closures.swift:7:17:7:17 | hello | closures.swift:12:6:12:6 | x | +| closures.swift:7:17:7:17 | hello | closures.swift:12:10:12:16 | call to hello() | +| closures.swift:11:23:11:23 | captureList | closures.swift:2:16:2:25 | label | +| closures.swift:11:23:11:23 | captureList | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:11:23:11:23 | captureList | closures.swift:2:33:2:42 | value | +| closures.swift:11:23:11:23 | captureList | closures.swift:2:59:2:59 | value | +| closures.swift:11:23:11:23 | captureList | closures.swift:11:7:11:7 | y | +| closures.swift:11:23:11:23 | captureList | closures.swift:11:7:11:10 | ... as ... | +| closures.swift:11:23:11:23 | captureList | closures.swift:11:16:11:41 | call to source(_:_:) | +| closures.swift:11:23:11:23 | captureList | closures.swift:11:38:11:38 | 123 | +| closures.swift:21:18:21:18 | setEscape | closures.swift:2:16:2:25 | label | +| closures.swift:21:18:21:18 | setEscape | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:21:18:21:18 | setEscape | closures.swift:2:33:2:42 | value | +| closures.swift:21:18:21:18 | setEscape | closures.swift:2:59:2:59 | value | +| closures.swift:21:18:21:18 | setEscape | closures.swift:21:7:21:7 | x | +| closures.swift:21:18:21:18 | setEscape | closures.swift:21:11:21:32 | call to source(_:_:) | +| closures.swift:21:18:21:18 | setEscape | closures.swift:21:31:21:31 | 0 | +| closures.swift:35:24:35:24 | logical | closures.swift:2:16:2:25 | label | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value | +| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x | +| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) | +| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 | +| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x | +| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0, ... (2)] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0, ... (3)] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0, ... (4)] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0, ... (5)] | +| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0] | +| closures.swift:48:50:48:50 | asyncTest | closures.swift:2:16:2:25 | label | +| closures.swift:48:50:48:50 | asyncTest | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:48:50:48:50 | asyncTest | closures.swift:2:33:2:42 | value | +| closures.swift:48:50:48:50 | asyncTest | closures.swift:2:59:2:59 | value | +| closures.swift:48:50:48:50 | asyncTest | closures.swift:44:18:44:23 | SSA def(x) | +| closures.swift:48:50:48:50 | asyncTest | closures.swift:44:18:44:23 | x | +| closures.swift:48:50:48:50 | asyncTest | closures.swift:45:29:45:29 | x | +| closures.swift:48:50:48:50 | asyncTest | closures.swift:48:43:48:65 | call to source(_:_:) | +| closures.swift:48:50:48:50 | asyncTest | closures.swift:48:63:48:63 | 40 | +| closures.swift:59:14:59:14 | foo | closures.swift:2:16:2:25 | label | +| closures.swift:59:14:59:14 | foo | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:59:14:59:14 | foo | closures.swift:2:33:2:42 | value | +| closures.swift:59:14:59:14 | foo | closures.swift:2:59:2:59 | value | +| closures.swift:59:14:59:14 | foo | closures.swift:59:7:59:23 | call to source(_:_:) | +| closures.swift:59:14:59:14 | foo | closures.swift:59:21:59:21 | 41 | +| closures.swift:69:14:69:14 | bar | closures.swift:2:16:2:25 | label | +| closures.swift:69:14:69:14 | bar | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:69:14:69:14 | bar | closures.swift:2:33:2:42 | value | +| closures.swift:69:14:69:14 | bar | closures.swift:2:59:2:59 | value | +| closures.swift:69:14:69:14 | bar | closures.swift:69:7:69:23 | call to source(_:_:) | +| closures.swift:69:14:69:14 | bar | closures.swift:69:21:69:21 | 41 | +| closures.swift:79:14:79:14 | baz | closures.swift:2:16:2:25 | label | +| closures.swift:79:14:79:14 | baz | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:79:14:79:14 | baz | closures.swift:2:33:2:42 | value | +| closures.swift:79:14:79:14 | baz | closures.swift:2:59:2:59 | value | +| closures.swift:79:14:79:14 | baz | closures.swift:79:7:79:23 | call to source(_:_:) | +| closures.swift:79:14:79:14 | baz | closures.swift:79:21:79:21 | 41 | +| closures.swift:87:20:87:20 | sharedCapture | closures.swift:2:16:2:25 | label | +| closures.swift:87:20:87:20 | sharedCapture | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:87:20:87:20 | sharedCapture | closures.swift:2:33:2:42 | value | +| closures.swift:87:20:87:20 | sharedCapture | closures.swift:2:59:2:59 | value | +| closures.swift:87:20:87:20 | sharedCapture | closures.swift:87:9:87:9 | x | +| closures.swift:87:20:87:20 | sharedCapture | closures.swift:87:13:87:38 | call to source(_:_:) | +| closures.swift:87:20:87:20 | sharedCapture | closures.swift:87:37:87:37 | 0 | +| closures.swift:114:35:114:35 | setter1 | closures.swift:2:16:2:25 | label | +| closures.swift:114:35:114:35 | setter1 | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:114:35:114:35 | setter1 | closures.swift:2:33:2:42 | value | +| closures.swift:114:35:114:35 | setter1 | closures.swift:2:59:2:59 | value | +| closures.swift:114:35:114:35 | setter1 | closures.swift:109:22:109:22 | y | +| closures.swift:114:35:114:35 | setter1 | closures.swift:114:28:114:47 | call to source(_:_:) | +| closures.swift:114:35:114:35 | setter1 | closures.swift:114:46:114:46 | 1 | +| closures.swift:115:35:115:35 | setter2 | closures.swift:2:16:2:25 | label | +| closures.swift:115:35:115:35 | setter2 | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:115:35:115:35 | setter2 | closures.swift:2:33:2:42 | value | +| closures.swift:115:35:115:35 | setter2 | closures.swift:2:59:2:59 | value | +| closures.swift:115:35:115:35 | setter2 | closures.swift:109:22:109:22 | y | +| closures.swift:115:35:115:35 | setter2 | closures.swift:115:28:115:47 | call to source(_:_:) | +| closures.swift:115:35:115:35 | setter2 | closures.swift:115:46:115:46 | 2 | diff --git a/swift/ql/test/library-tests/dataflow/capture/partialflowtest.ql b/swift/ql/test/library-tests/dataflow/capture/partialflowtest.ql new file mode 100644 index 000000000000..34593374bccb --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/capture/partialflowtest.ql @@ -0,0 +1,32 @@ +import swift +import codeql.swift.dataflow.DataFlow + +predicate source(StringLiteralExpr label, Expr value) { + exists(ApplyExpr ae | + ae.getStaticTarget().hasName(["source(_:_:)", "taint(_:_:)"]) and + ae.getFile().getBaseName() = "closures.swift" + | + ae.getArgument(0).getExpr() = label and + ae.getArgument(1).getExpr() = value + ) +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { source(n.asExpr(), _) } + + predicate isSink(DataFlow::Node n) { none() } + + predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + source(n1.asExpr(), n2.asExpr()) + } +} + +module Flow = DataFlow::Global; + +int explorationLimit() { result = 100 } + +module PartialFlow = Flow::FlowExploration; + +from PartialFlow::PartialPathNode src, PartialFlow::PartialPathNode sink +where PartialFlow::partialFlow(src, sink, _) +select src, sink From 4b841b0cafc11c7e935cfaeaca801e8106678044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Tue, 29 Aug 2023 17:32:33 +0200 Subject: [PATCH 04/13] Swift: s/getName/getShortName/ in InlineFlowTest.qll --- swift/ql/test/TestUtilities/InlineFlowTest.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swift/ql/test/TestUtilities/InlineFlowTest.qll b/swift/ql/test/TestUtilities/InlineFlowTest.qll index 4dcd1fb8bc57..5ddad0abab66 100644 --- a/swift/ql/test/TestUtilities/InlineFlowTest.qll +++ b/swift/ql/test/TestUtilities/InlineFlowTest.qll @@ -42,11 +42,11 @@ import codeql.swift.dataflow.TaintTracking import TestUtilities.InlineExpectationsTest private predicate defaultSource(DataFlow::Node source) { - source.asExpr().(MethodCallExpr).getStaticTarget().getName() = ["source", "taint"] + source.asExpr().(MethodCallExpr).getStaticTarget().getShortName() = ["source", "taint"] } private predicate defaultSink(DataFlow::Node sink) { - exists(MethodCallExpr ma | ma.getStaticTarget().hasName("sink") | + exists(MethodCallExpr ma | ma.getStaticTarget().getShortName() = "sink" | sink.asExpr() = ma.getAnArgument().getExpr() ) } From 88b54f88d637829652dc0ec9b54d5986ae095c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 30 Aug 2023 20:47:50 +0200 Subject: [PATCH 05/13] Swift: initial version of a swift port of most of the java code --- .../dataflow/internal/DataFlowPrivate.qll | 151 +++++++++++++++++- .../dataflow/internal/DataFlowPublic.qll | 34 +++- 2 files changed, 177 insertions(+), 8 deletions(-) diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index a84abfa2d7c5..f3571ba2ab36 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -9,6 +9,7 @@ private import codeql.swift.dataflow.FlowSummary as FlowSummary private import codeql.swift.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import codeql.swift.frameworks.StandardLibrary.PointerTypes private import codeql.swift.frameworks.StandardLibrary.Array +private import codeql.dataflow.VariableCapture as VariableCapture /** Gets the callable in which this node occurs. */ DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.(NodeImpl).getEnclosingCallable() } @@ -75,6 +76,16 @@ private class SsaDefinitionNodeImpl extends SsaDefinitionNode, NodeImpl { } } +private class CaptureNodeImpl extends CaptureNode, NodeImpl { + override Location getLocationImpl() { result = this.getSynthesizedCaptureNode().getLocation() } + + override string toStringImpl() { result = this.getSynthesizedCaptureNode().toString() } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.getSynthesizedCaptureNode().getEnclosingCallable() + } +} + private predicate localFlowSsaInput(Node nodeFrom, Ssa::Definition def, Ssa::Definition next) { exists(BasicBlock bb, int i | def.lastRefRedef(bb, i, next) | def.definesAt(_, bb, i) and @@ -114,7 +125,8 @@ private module Cached { any(ApplyExpr apply).getQualifier(), any(TupleElementExpr te).getSubExpr(), any(SubscriptExpr se).getBase() ]) - } + } or + TCaptureNode(CaptureFlow::SynthesizedCaptureNode cn) private predicate localSsaFlowStepUseUse(Ssa::Definition def, Node nodeFrom, Node nodeTo) { def.adjacentReadPair(nodeFrom.getCfgNode(), nodeTo.getCfgNode()) and @@ -257,7 +269,8 @@ private module Cached { TTupleContent(int index) { exists(any(TupleExpr te).getElement(index)) } or TEnumContent(ParamDecl f) { exists(EnumElementDecl d | d.getAParam() = f) } or TArrayContent() or - TCollectionContent() + TCollectionContent() or + TCapturedVariableContent(CapturedVariable v) } /** @@ -301,7 +314,7 @@ private module ParameterNodes { predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { none() } /** Gets the parameter associated with this node, if any. */ - ParamDecl getParameter() { none() } + override ParamDecl getParameter() { none() } } class SourceParameterNode extends ParameterNodeImpl, TSourceParameterNode { @@ -524,7 +537,7 @@ private module ReturnNodes { result = TDataFlowFunc(param.getDeclaringFunction()) } - ParamDecl getParameter() { result = param } + override ParamDecl getParameter() { result = param } override Location getLocationImpl() { result = exit.getLocation() } @@ -651,6 +664,136 @@ private module OutNodes { import OutNodes +private predicate closureFlowStep(Expr e1, Expr e2) { + // simpleLocalFlowStep(exprNode(e1), exprNode(e2)) // TODO: find out why the java version uses simpleAstFlowStep... probably due to non-monotonic recursion + // or + exists(Ssa::WriteDefinition def | + def.getARead().getNode().asAstNode() = e2 and + def.assigns(any(CfgNode cfg | cfg.getNode().asAstNode() = e1)) + ) +} + +private module CaptureInput implements VariableCapture::InputSig { + private import swift as S + private import codeql.swift.controlflow.BasicBlocks as B + + class Location = S::Location; + + class BasicBlock instanceof B::BasicBlock { + string toString() { result = super.toString() } + + Callable getEnclosingCallable() { result = super.getScope() } + + Location getLocation() { result = super.getLocation() } + } + + BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.(B::BasicBlock).dominates(bb) } + + BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.(B::BasicBlock).getASuccessor() } + + //TODO: support capture of `this` in lambdas + class CapturedVariable instanceof S::CapturedDecl { + string toString() { result = super.toString() } + + Callable getCallable() { result = super.getScope() } + + Location getLocation() { result = super.getLocation() } + } + + class CapturedParameter extends CapturedVariable { + CapturedParameter() { this.(S::CapturedDecl).getDecl() instanceof S::ParamDecl } + } + + class Expr instanceof S::AstNode { + string toString() { result = super.toString() } + + Location getLocation() { result = super.getLocation() } + + predicate hasCfgNode(BasicBlock bb, int i) { + this = bb.(B::BasicBlock).getNode(i).getNode().asAstNode() + } + } + + class VariableWrite extends Expr { + CapturedVariable variable; + Expr source; + + VariableWrite() { + exists(S::VarDecl varDecl | + variable.(S::CapturedDecl).getDecl() = varDecl and + variable.getCallable() = this.(S::AstNode).getEnclosingCallable() + | + exists(S::Assignment a | this = a | + a.getDest().(DeclRefExpr).getDecl() = varDecl and + source = a.getSource() + ) + or + exists(S::PatternBindingDecl pbd, S::NamedPattern np | + this = pbd and pbd.getAPattern() = np + | + np.getVarDecl() = varDecl and + source = np.getMatchingExpr() + ) + // TODO: support multiple variables in LHS of =, in both of above cases. + ) + } + + CapturedVariable getVariable() { result = variable } + + Expr getSource() { result = source } + } + + class VariableRead extends Expr instanceof S::DeclRefExpr { + CapturedVariable v; + + VariableRead() { this.getCapturedDecl() = v /* TODO: this should be an R-value only. */ } + + CapturedVariable getVariable() { result = v } + } + + class ClosureExpr extends Expr instanceof S::Callable { + ClosureExpr() { any(S::CapturedDecl c).getScope() = this } + + predicate hasBody(Callable body) { this = body } + + predicate hasAliasedAccess(Expr f) { + closureFlowStep+(this, f) and not closureFlowStep(f, _) + /* TODO: understand why this is intra-procedural */ } + } + + class Callable extends S::Callable { + predicate isConstructor() { this instanceof S::Initializer } + } +} + +class CapturedVariable = CaptureInput::CapturedVariable; + +class CapturedParameter = CaptureInput::CapturedParameter; + +module CaptureFlow = VariableCapture::Flow; + +private CaptureFlow::ClosureNode asClosureNode(Node n) { + result = n.(CaptureNode).getSynthesizedCaptureNode() or + result.(CaptureFlow::ExprNode).getExpr() = n.asExpr() or + result.(CaptureFlow::ExprPostUpdateNode).getExpr() = + n.(PostUpdateNode).getPreUpdateNode().asExpr() or + result.(CaptureFlow::ParameterNode).getParameter().(CapturedDecl).getDecl() = n.getParameter() or + result.(CaptureFlow::ThisParameterNode).getCallable().getSelfParam() = n.getParameter() or + result.(CaptureFlow::MallocNode).getClosureExpr() = n.getCfgNode().getNode().asAstNode() // TODO: figure out why the java version had PostUpdateNode logic here +} + +private predicate captureStoreStep(Node node1, Content::CapturedVariableContent c, Node node2) { + CaptureFlow::storeStep(asClosureNode(node1), c.getVariable(), asClosureNode(node2)) +} + +private predicate captureReadStep(Node node1, Content::CapturedVariableContent c, Node node2) { + CaptureFlow::readStep(asClosureNode(node1), c.getVariable(), asClosureNode(node2)) +} + +predicate captureValueStep(Node node1, Node node2) { + CaptureFlow::localFlowStep(asClosureNode(node1), asClosureNode(node2)) +} + predicate jumpStep(Node pred, Node succ) { FlowSummaryImpl::Private::Steps::summaryJumpStep(pred.(FlowSummaryNode).getSummaryNode(), succ.(FlowSummaryNode).getSummaryNode()) diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll index 04ab0e27a102..302a727456b7 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll @@ -51,6 +51,11 @@ class Node extends TNode { * Gets this node's underlying SSA definition, if any. */ Ssa::Definition asDefinition() { none() } + + /** + * Gets the parameter that corresponds to this node, if any. + */ + ParamDecl getParameter() { none() } } /** @@ -96,7 +101,7 @@ class ParameterNode extends Node instanceof ParameterNodeImpl { result = this.(ParameterNodeImpl).getEnclosingCallable() } - ParamDecl getParameter() { result = this.(ParameterNodeImpl).getParameter() } + override ParamDecl getParameter() { result = this.(ParameterNodeImpl).getParameter() } } /** @@ -109,9 +114,7 @@ class SsaDefinitionNode extends Node, TSsaDefinitionNode { override Ssa::Definition asDefinition() { result = def } } -class InoutReturnNode extends Node instanceof InoutReturnNodeImpl { - ParamDecl getParameter() { result = super.getParameter() } -} +class InoutReturnNode extends Node instanceof InoutReturnNodeImpl { } /** * A node associated with an object after an operation that might have @@ -129,6 +132,18 @@ class PostUpdateNode extends Node instanceof PostUpdateNodeImpl { Node getPreUpdateNode() { result = super.getPreUpdateNode() } } +/** + * A synthesized data flow node representing a closure object that tracks + * captured variables. + */ +class CaptureNode extends Node, TCaptureNode { + private CaptureFlow::SynthesizedCaptureNode cn; + + CaptureNode() { this = TCaptureNode(cn) } + + CaptureFlow::SynthesizedCaptureNode getSynthesizedCaptureNode() { result = cn } +} + /** * Gets a node corresponding to expression `e`. */ @@ -234,6 +249,17 @@ module Content { class CollectionContent extends Content, TCollectionContent { override string toString() { result = "Collection element" } } + + /** A captured variable. */ + class CapturedVariableContent extends Content, TCapturedVariableContent { + CapturedVariable v; + + CapturedVariableContent() { this = TCapturedVariableContent(v) } + + CapturedVariable getVariable() { result = v } + + override string toString() { result = v.toString() } + } } /** From 7f55d6fab42a16243f63768fc26f1cceddaa979e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Tue, 5 Sep 2023 14:28:56 +0200 Subject: [PATCH 06/13] Swift: getImmediateBasicBlockDominator/2 should use immediatelyDominates/0. --- .../ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll | 4 +++- 1 file changed, 3 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 f3571ba2ab36..631aee46c7c1 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -687,7 +687,9 @@ private module CaptureInput implements VariableCapture::InputSig { Location getLocation() { result = super.getLocation() } } - BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.(B::BasicBlock).dominates(bb) } + BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { + result.(B::BasicBlock).immediatelyDominates(bb) + } BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.(B::BasicBlock).getASuccessor() } From f8faba6af1b237ea1100fba9c65f006c7e7dbc67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Mon, 11 Sep 2023 14:28:07 +0200 Subject: [PATCH 07/13] Swift: Add closure content read-write steps --- .../ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index 631aee46c7c1..e1081ebb1d12 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -882,6 +882,8 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { or FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c, node2.(FlowSummaryNode).getSummaryNode()) + or + captureStoreStep(node1, any(Content::CapturedVariableContent cvc | c.isSingleton(cvc)), node2) } predicate isLValue(Expr e) { any(AssignExpr assign).getDest() = e } @@ -973,6 +975,8 @@ predicate readStep(Node node1, ContentSet c, Node node2) { or FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c, node2.(FlowSummaryNode).getSummaryNode()) + or + captureReadStep(node1, any(Content::CapturedVariableContent cvc | c.isSingleton(cvc)), node2) } /** From 12165e8cc29789d67e1440f0daeff4aea556c257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Mon, 11 Sep 2023 17:15:21 +0200 Subject: [PATCH 08/13] Swift: port simpleAstFlowStep/hasAliasedAccess --- .../dataflow/internal/DataFlowPrivate.qll | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index e1081ebb1d12..a744dfaf0525 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -664,9 +664,21 @@ private module OutNodes { import OutNodes +/** + * Holds if there is a data flow step from `e1` to `e2` that only steps from + * child to parent in the AST. + */ +private predicate simpleAstFlowStep(Expr e1, Expr e2) { + e2.(IfExpr).getBranch(_) = e1 + or + e2.(AssignExpr).getSource() = e1 + or + e2.(ArrayExpr).getAnElement() = e1 +} + private predicate closureFlowStep(Expr e1, Expr e2) { - // simpleLocalFlowStep(exprNode(e1), exprNode(e2)) // TODO: find out why the java version uses simpleAstFlowStep... probably due to non-monotonic recursion - // or + simpleAstFlowStep(e1, e2) + or exists(Ssa::WriteDefinition def | def.getARead().getNode().asAstNode() = e2 and def.assigns(any(CfgNode cfg | cfg.getNode().asAstNode() = e1)) @@ -758,9 +770,7 @@ private module CaptureInput implements VariableCapture::InputSig { predicate hasBody(Callable body) { this = body } - predicate hasAliasedAccess(Expr f) { - closureFlowStep+(this, f) and not closureFlowStep(f, _) - /* TODO: understand why this is intra-procedural */ } + predicate hasAliasedAccess(Expr f) { closureFlowStep+(this, f) and not closureFlowStep(f, _) } } class Callable extends S::Callable { From 7c8414a400746bfdba8695db9d8a012e6316dae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Mon, 11 Sep 2023 17:42:13 +0200 Subject: [PATCH 09/13] Swift: Add the capture flow step as part of the normal data flow relation TODO: see if we need to exclude duplicate SSA steps --- .../ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index 0287a6e0de72..fc403d3da8dd 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -246,6 +246,9 @@ private module Cached { // flow through a flow summary (extension of `SummaryModelCsv`) FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), nodeTo.(FlowSummaryNode).getSummaryNode(), true) + or + // flow step according to the closure capture library + captureValueStep(nodeFrom, nodeTo) } /** From bb42d73124f5ab7b4872df9bf19e796e4eb1f7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Mon, 11 Sep 2023 18:31:08 +0200 Subject: [PATCH 10/13] Swift: accept new results in old tests --- .../test/library-tests/dataflow/taint/libraries/int.swift | 2 +- .../Security/CWE-134/UncontrolledFormatString.expected | 7 +++++++ .../Security/CWE-134/UncontrolledFormatString.swift | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/swift/ql/test/library-tests/dataflow/taint/libraries/int.swift b/swift/ql/test/library-tests/dataflow/taint/libraries/int.swift index c4cd65dade5f..f1f868c4df4e 100644 --- a/swift/ql/test/library-tests/dataflow/taint/libraries/int.swift +++ b/swift/ql/test/library-tests/dataflow/taint/libraries/int.swift @@ -147,7 +147,7 @@ func taintCollections(array: inout Array, contiguousArray: inout Contiguous sink(arg: buffer) sink(arg: buffer[0]) // $ tainted=142 sink(arg: array) - sink(arg: array[0]) // $ MISSING: tainted=142 + sink(arg: array[0]) // $ tainted=142 }) contiguousArray[0] = source2() diff --git a/swift/ql/test/query-tests/Security/CWE-134/UncontrolledFormatString.expected b/swift/ql/test/query-tests/Security/CWE-134/UncontrolledFormatString.expected index 3a2d4eb80c6a..7d03fb6562e3 100644 --- a/swift/ql/test/query-tests/Security/CWE-134/UncontrolledFormatString.expected +++ b/swift/ql/test/query-tests/Security/CWE-134/UncontrolledFormatString.expected @@ -1,4 +1,5 @@ edges +| UncontrolledFormatString.swift:57:12:57:22 | format | UncontrolledFormatString.swift:59:16:59:16 | format | | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:70:28:70:28 | tainted | | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:73:28:73:28 | tainted | | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:74:28:74:28 | tainted | @@ -11,12 +12,16 @@ edges | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:84:54:84:54 | tainted | | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:85:72:85:72 | tainted | | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:88:11:88:11 | tainted | +| UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:89:11:89:11 | tainted | | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:91:61:91:61 | tainted | | UncontrolledFormatString.swift:81:47:81:47 | tainted | UncontrolledFormatString.swift:81:30:81:54 | call to NSString.init(string:) | | UncontrolledFormatString.swift:82:65:82:65 | tainted | UncontrolledFormatString.swift:82:48:82:72 | call to NSString.init(string:) | | UncontrolledFormatString.swift:84:54:84:54 | tainted | UncontrolledFormatString.swift:84:37:84:61 | call to NSString.init(string:) | | UncontrolledFormatString.swift:85:72:85:72 | tainted | UncontrolledFormatString.swift:85:55:85:79 | call to NSString.init(string:) | +| UncontrolledFormatString.swift:89:11:89:11 | tainted | UncontrolledFormatString.swift:57:12:57:22 | format | nodes +| UncontrolledFormatString.swift:57:12:57:22 | format | semmle.label | format | +| UncontrolledFormatString.swift:59:16:59:16 | format | semmle.label | format | | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) | | UncontrolledFormatString.swift:70:28:70:28 | tainted | semmle.label | tainted | | UncontrolledFormatString.swift:73:28:73:28 | tainted | semmle.label | tainted | @@ -34,9 +39,11 @@ nodes | UncontrolledFormatString.swift:85:55:85:79 | call to NSString.init(string:) | semmle.label | call to NSString.init(string:) | | UncontrolledFormatString.swift:85:72:85:72 | tainted | semmle.label | tainted | | UncontrolledFormatString.swift:88:11:88:11 | tainted | semmle.label | tainted | +| UncontrolledFormatString.swift:89:11:89:11 | tainted | semmle.label | tainted | | UncontrolledFormatString.swift:91:61:91:61 | tainted | semmle.label | tainted | subpaths #select +| UncontrolledFormatString.swift:59:16:59:16 | format | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:59:16:59:16 | format | This format string depends on $@. | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | this user-provided value | | UncontrolledFormatString.swift:70:28:70:28 | tainted | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:70:28:70:28 | tainted | This format string depends on $@. | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | this user-provided value | | UncontrolledFormatString.swift:73:28:73:28 | tainted | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:73:28:73:28 | tainted | This format string depends on $@. | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | this user-provided value | | UncontrolledFormatString.swift:74:28:74:28 | tainted | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:74:28:74:28 | tainted | This format string depends on $@. | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | this user-provided value | diff --git a/swift/ql/test/query-tests/Security/CWE-134/UncontrolledFormatString.swift b/swift/ql/test/query-tests/Security/CWE-134/UncontrolledFormatString.swift index e5665eedeac7..05fc1cb25648 100644 --- a/swift/ql/test/query-tests/Security/CWE-134/UncontrolledFormatString.swift +++ b/swift/ql/test/query-tests/Security/CWE-134/UncontrolledFormatString.swift @@ -56,7 +56,7 @@ func getVaList(_ args: [CVarArg]) -> CVaListPointer { return (nil as CVaListPoin func MyLog(_ format: String, _ args: CVarArg...) { withVaList(args) { arglist in - NSLogv(format, arglist) // BAD [NOT DETECTED] + NSLogv(format, arglist) // BAD } } From c49960aa1603438578588f507ce212af143e7cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 14 Sep 2023 16:46:23 +0200 Subject: [PATCH 11/13] Swift: add and accept a few new simple test cases --- .../ql/test/TestUtilities/InlineFlowTest.qll | 8 +- .../dataflow/capture/closures.swift | 25 +- .../dataflow/capture/partialflowtest.expected | 339 +++++++++++------- 3 files changed, 232 insertions(+), 140 deletions(-) diff --git a/swift/ql/test/TestUtilities/InlineFlowTest.qll b/swift/ql/test/TestUtilities/InlineFlowTest.qll index 5ddad0abab66..4ab2a7cdf38f 100644 --- a/swift/ql/test/TestUtilities/InlineFlowTest.qll +++ b/swift/ql/test/TestUtilities/InlineFlowTest.qll @@ -42,12 +42,12 @@ import codeql.swift.dataflow.TaintTracking import TestUtilities.InlineExpectationsTest private predicate defaultSource(DataFlow::Node source) { - source.asExpr().(MethodCallExpr).getStaticTarget().getShortName() = ["source", "taint"] + source.asExpr().(CallExpr).getStaticTarget().(Function).getShortName() = ["source", "taint"] } private predicate defaultSink(DataFlow::Node sink) { - exists(MethodCallExpr ma | ma.getStaticTarget().getShortName() = "sink" | - sink.asExpr() = ma.getAnArgument().getExpr() + exists(CallExpr ca | ca.getStaticTarget().(Function).getShortName() = "sink" | + sink.asExpr() = ca.getAnArgument().getExpr() ) } @@ -67,7 +67,7 @@ private module NoFlowConfig implements DataFlow::ConfigSig { private string getSourceArgString(DataFlow::Node src) { defaultSource(src) and - src.asExpr().(MethodCallExpr).getAnArgument().getExpr().(StringLiteralExpr).getValue() = result + src.asExpr().(CallExpr).getAnArgument().getExpr().(StringLiteralExpr).getValue() = result } module FlowTest { diff --git a/swift/ql/test/library-tests/dataflow/capture/closures.swift b/swift/ql/test/library-tests/dataflow/capture/closures.swift index 8260782e129c..cb99f9fbbd5e 100644 --- a/swift/ql/test/library-tests/dataflow/capture/closures.swift +++ b/swift/ql/test/library-tests/dataflow/capture/closures.swift @@ -18,7 +18,7 @@ func captureList() { var escape: (() -> Int)? = nil func setEscape() { - var x = source("setEscape", 0) + let x = source("setEscape", 0) escape = { sink(x) // $ MISSING: hasValueFlow=setEscape return x + 1 @@ -31,11 +31,15 @@ func callEscape() { } func logical() -> Bool { - let f: ((Int) -> Int)? = { x in x + 1 } + let f: ((Int) -> Int)? = { x in + sink(x) // $ hasValueFlow=logical + return x + 1 + } + let x: Int? = source("logical", 42) return f != nil && (x != nil - && f!(x!) == 43) // $ MISSING: hasValueFlow=logical + && f!(x!) == 43) } func asyncTest() { @@ -121,6 +125,21 @@ func sharedCaptureMultipleWriters() { callSink2() } +func taintCollections(array: inout Array) { + array[0] = source("array", 0) + sink(array) + sink(array[0]) // $ hasValueFlow=array + array.withContiguousStorageIfAvailable({ + buffer in + sink(array) + sink(array[0]) // $ hasValueFlow=array + }) +} + +func simplestTest() { + let x = source("simplestTest", 0) + sink(x) // $ hasValueFlow=simplestTest +} func main() { print("captureList():") diff --git a/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected b/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected index 86ab8a7c05a1..2d86d30449f3 100644 --- a/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected +++ b/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected @@ -21,136 +21,209 @@ | closures.swift:21:18:21:18 | setEscape | closures.swift:21:7:21:7 | x | | closures.swift:21:18:21:18 | setEscape | closures.swift:21:11:21:32 | call to source(_:_:) | | closures.swift:21:18:21:18 | setEscape | closures.swift:21:31:21:31 | 0 | -| closures.swift:35:24:35:24 | logical | closures.swift:2:16:2:25 | label | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:33:2:42 | value [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value | -| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:2:59:2:59 | value [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:30:34:30 | x [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x | -| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:34:35:34:35 | x [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | SSA def(x) [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:7 | x [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:7:35:13 | ... as ... [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) | -| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:17:35:37 | call to source(_:_:) [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 | -| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:35:35:35:35 | 42 [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x | -| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:37:11:37:11 | x [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:17 | x [some:0] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0, ... (2)] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0, ... (3)] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0, ... (4)] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0, ... (5)] | -| closures.swift:35:24:35:24 | logical | closures.swift:38:17:38:18 | ...! [some:0] | -| closures.swift:48:50:48:50 | asyncTest | closures.swift:2:16:2:25 | label | -| closures.swift:48:50:48:50 | asyncTest | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:48:50:48:50 | asyncTest | closures.swift:2:33:2:42 | value | -| closures.swift:48:50:48:50 | asyncTest | closures.swift:2:59:2:59 | value | -| closures.swift:48:50:48:50 | asyncTest | closures.swift:44:18:44:23 | SSA def(x) | -| closures.swift:48:50:48:50 | asyncTest | closures.swift:44:18:44:23 | x | -| closures.swift:48:50:48:50 | asyncTest | closures.swift:45:29:45:29 | x | -| closures.swift:48:50:48:50 | asyncTest | closures.swift:48:43:48:65 | call to source(_:_:) | -| closures.swift:48:50:48:50 | asyncTest | closures.swift:48:63:48:63 | 40 | -| closures.swift:59:14:59:14 | foo | closures.swift:2:16:2:25 | label | -| closures.swift:59:14:59:14 | foo | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:59:14:59:14 | foo | closures.swift:2:33:2:42 | value | -| closures.swift:59:14:59:14 | foo | closures.swift:2:59:2:59 | value | -| closures.swift:59:14:59:14 | foo | closures.swift:59:7:59:23 | call to source(_:_:) | -| closures.swift:59:14:59:14 | foo | closures.swift:59:21:59:21 | 41 | -| closures.swift:69:14:69:14 | bar | closures.swift:2:16:2:25 | label | -| closures.swift:69:14:69:14 | bar | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:69:14:69:14 | bar | closures.swift:2:33:2:42 | value | -| closures.swift:69:14:69:14 | bar | closures.swift:2:59:2:59 | value | -| closures.swift:69:14:69:14 | bar | closures.swift:69:7:69:23 | call to source(_:_:) | -| closures.swift:69:14:69:14 | bar | closures.swift:69:21:69:21 | 41 | -| closures.swift:79:14:79:14 | baz | closures.swift:2:16:2:25 | label | -| closures.swift:79:14:79:14 | baz | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:79:14:79:14 | baz | closures.swift:2:33:2:42 | value | -| closures.swift:79:14:79:14 | baz | closures.swift:2:59:2:59 | value | -| closures.swift:79:14:79:14 | baz | closures.swift:79:7:79:23 | call to source(_:_:) | -| closures.swift:79:14:79:14 | baz | closures.swift:79:21:79:21 | 41 | -| closures.swift:87:20:87:20 | sharedCapture | closures.swift:2:16:2:25 | label | -| closures.swift:87:20:87:20 | sharedCapture | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:87:20:87:20 | sharedCapture | closures.swift:2:33:2:42 | value | -| closures.swift:87:20:87:20 | sharedCapture | closures.swift:2:59:2:59 | value | -| closures.swift:87:20:87:20 | sharedCapture | closures.swift:87:9:87:9 | x | -| closures.swift:87:20:87:20 | sharedCapture | closures.swift:87:13:87:38 | call to source(_:_:) | -| closures.swift:87:20:87:20 | sharedCapture | closures.swift:87:37:87:37 | 0 | -| closures.swift:114:35:114:35 | setter1 | closures.swift:2:16:2:25 | label | -| closures.swift:114:35:114:35 | setter1 | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:114:35:114:35 | setter1 | closures.swift:2:33:2:42 | value | -| closures.swift:114:35:114:35 | setter1 | closures.swift:2:59:2:59 | value | -| closures.swift:114:35:114:35 | setter1 | closures.swift:109:22:109:22 | y | -| closures.swift:114:35:114:35 | setter1 | closures.swift:114:28:114:47 | call to source(_:_:) | -| closures.swift:114:35:114:35 | setter1 | closures.swift:114:46:114:46 | 1 | -| closures.swift:115:35:115:35 | setter2 | closures.swift:2:16:2:25 | label | -| closures.swift:115:35:115:35 | setter2 | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:115:35:115:35 | setter2 | closures.swift:2:33:2:42 | value | -| closures.swift:115:35:115:35 | setter2 | closures.swift:2:59:2:59 | value | -| closures.swift:115:35:115:35 | setter2 | closures.swift:109:22:109:22 | y | -| closures.swift:115:35:115:35 | setter2 | closures.swift:115:28:115:47 | call to source(_:_:) | -| closures.swift:115:35:115:35 | setter2 | closures.swift:115:46:115:46 | 2 | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value | +| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:16:2:25 | label | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value | +| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x | +| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x | +| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) | +| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 | +| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x | +| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0, ... (2)] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0, ... (3)] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0, ... (4)] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0, ... (5)] | +| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0] | +| closures.swift:52:50:52:50 | asyncTest | closures.swift:2:16:2:25 | label | +| closures.swift:52:50:52:50 | asyncTest | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:52:50:52:50 | asyncTest | closures.swift:2:33:2:42 | value | +| closures.swift:52:50:52:50 | asyncTest | closures.swift:2:59:2:59 | value | +| closures.swift:52:50:52:50 | asyncTest | closures.swift:48:18:48:23 | SSA def(x) | +| closures.swift:52:50:52:50 | asyncTest | closures.swift:48:18:48:23 | x | +| closures.swift:52:50:52:50 | asyncTest | closures.swift:49:29:49:29 | x | +| closures.swift:52:50:52:50 | asyncTest | closures.swift:52:43:52:65 | call to source(_:_:) | +| closures.swift:52:50:52:50 | asyncTest | closures.swift:52:63:52:63 | 40 | +| closures.swift:63:14:63:14 | foo | closures.swift:2:16:2:25 | label | +| closures.swift:63:14:63:14 | foo | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:63:14:63:14 | foo | closures.swift:2:33:2:42 | value | +| closures.swift:63:14:63:14 | foo | closures.swift:2:59:2:59 | value | +| closures.swift:63:14:63:14 | foo | closures.swift:63:7:63:23 | call to source(_:_:) | +| closures.swift:63:14:63:14 | foo | closures.swift:63:21:63:21 | 41 | +| closures.swift:73:14:73:14 | bar | closures.swift:2:16:2:25 | label | +| closures.swift:73:14:73:14 | bar | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:73:14:73:14 | bar | closures.swift:2:33:2:42 | value | +| closures.swift:73:14:73:14 | bar | closures.swift:2:59:2:59 | value | +| closures.swift:73:14:73:14 | bar | closures.swift:73:7:73:23 | call to source(_:_:) | +| closures.swift:73:14:73:14 | bar | closures.swift:73:21:73:21 | 41 | +| closures.swift:83:14:83:14 | baz | closures.swift:2:16:2:25 | label | +| closures.swift:83:14:83:14 | baz | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:83:14:83:14 | baz | closures.swift:2:33:2:42 | value | +| closures.swift:83:14:83:14 | baz | closures.swift:2:59:2:59 | value | +| closures.swift:83:14:83:14 | baz | closures.swift:83:7:83:23 | call to source(_:_:) | +| closures.swift:83:14:83:14 | baz | closures.swift:83:21:83:21 | 41 | +| closures.swift:91:20:91:20 | sharedCapture | closures.swift:2:16:2:25 | label | +| closures.swift:91:20:91:20 | sharedCapture | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:91:20:91:20 | sharedCapture | closures.swift:2:33:2:42 | value | +| closures.swift:91:20:91:20 | sharedCapture | closures.swift:2:59:2:59 | value | +| closures.swift:91:20:91:20 | sharedCapture | closures.swift:91:9:91:9 | x | +| closures.swift:91:20:91:20 | sharedCapture | closures.swift:91:13:91:38 | call to source(_:_:) | +| closures.swift:91:20:91:20 | sharedCapture | closures.swift:91:37:91:37 | 0 | +| closures.swift:118:35:118:35 | setter1 | closures.swift:2:16:2:25 | label | +| closures.swift:118:35:118:35 | setter1 | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:118:35:118:35 | setter1 | closures.swift:2:33:2:42 | value | +| closures.swift:118:35:118:35 | setter1 | closures.swift:2:59:2:59 | value | +| closures.swift:118:35:118:35 | setter1 | closures.swift:113:22:113:22 | y | +| closures.swift:118:35:118:35 | setter1 | closures.swift:118:28:118:47 | call to source(_:_:) | +| closures.swift:118:35:118:35 | setter1 | closures.swift:118:46:118:46 | 1 | +| closures.swift:119:35:119:35 | setter2 | closures.swift:2:16:2:25 | label | +| closures.swift:119:35:119:35 | setter2 | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:119:35:119:35 | setter2 | closures.swift:2:33:2:42 | value | +| closures.swift:119:35:119:35 | setter2 | closures.swift:2:59:2:59 | value | +| closures.swift:119:35:119:35 | setter2 | closures.swift:113:22:113:22 | y | +| closures.swift:119:35:119:35 | setter2 | closures.swift:119:28:119:47 | call to source(_:_:) | +| closures.swift:119:35:119:35 | setter2 | closures.swift:119:46:119:46 | 2 | +| closures.swift:129:21:129:21 | array | closures.swift:1:14:1:23 | SSA def(value) | +| closures.swift:129:21:129:21 | array | closures.swift:1:14:1:23 | SSA def(value) [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:1:14:1:23 | value | +| closures.swift:129:21:129:21 | array | closures.swift:1:14:1:23 | value [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:1:34:1:43 | [...] [Array element, ... (2)] | +| closures.swift:129:21:129:21 | array | closures.swift:1:34:1:43 | [...] [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:1:43:1:43 | value | +| closures.swift:129:21:129:21 | array | closures.swift:1:43:1:43 | value [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:2:16:2:25 | label | +| closures.swift:129:21:129:21 | array | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:129:21:129:21 | array | closures.swift:2:33:2:42 | value | +| closures.swift:129:21:129:21 | array | closures.swift:2:59:2:59 | value | +| closures.swift:129:21:129:21 | array | closures.swift:128:1:137:1 | array[return] [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:129:3:129:3 | &... [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:129:3:129:3 | [post] array [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:129:14:129:31 | call to source(_:_:) | +| closures.swift:129:21:129:21 | array | closures.swift:129:30:129:30 | 0 | +| closures.swift:129:21:129:21 | array | closures.swift:130:8:130:8 | array [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:131:8:131:8 | &... [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:131:8:131:8 | array [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:131:8:131:15 | ...[...] | +| closures.swift:129:21:129:21 | array | closures.swift:132:3:132:3 | array [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:133:5:133:5 | buffer [Collection element] | +| closures.swift:129:21:129:21 | array | closures.swift:134:10:134:10 | array [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:135:10:135:10 | &... [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:135:10:135:10 | array [Array element] | +| closures.swift:129:21:129:21 | array | closures.swift:135:10:135:17 | ...[...] | +| closures.swift:129:21:129:21 | array | file://:0:0:0:0 | [summary param] this in withContiguousStorageIfAvailable(_:) [Array element] | +| closures.swift:129:21:129:21 | array | file://:0:0:0:0 | [summary] read: Argument[this].ArrayElement in withContiguousStorageIfAvailable(_:) | +| closures.swift:129:21:129:21 | array | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in withContiguousStorageIfAvailable(_:) [Collection element] | +| closures.swift:129:21:129:21 | array | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0].CollectionElement in withContiguousStorageIfAvailable(_:) | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:1:14:1:23 | SSA def(value) | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:1:14:1:23 | value | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:1:34:1:43 | [...] [Array element] | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:1:43:1:43 | value | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:2:16:2:25 | label | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:2:33:2:42 | value | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:2:59:2:59 | value | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:140:7:140:7 | SSA def(x) | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:140:7:140:7 | x | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:140:11:140:35 | call to source(_:_:) | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:140:34:140:34 | 0 | +| closures.swift:140:18:140:18 | simplestTest | closures.swift:141:8:141:8 | x | From 4e1472b32d9b39125850091675f6400a968b3f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Mon, 18 Sep 2023 20:34:53 +0200 Subject: [PATCH 12/13] Swift: align definition of InputSig slightly closer to Java version Though there is a regression in the tests, so more work is needed. --- .../dataflow/internal/DataFlowPrivate.qll | 42 +- .../dataflow/capture/closures.swift | 13 +- .../dataflow/capture/partialflowtest.expected | 453 ++++++++++-------- 3 files changed, 271 insertions(+), 237 deletions(-) diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index fc403d3da8dd..afcd6e1def72 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -735,17 +735,20 @@ private module CaptureInput implements VariableCapture::InputSig { BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.(B::BasicBlock).getASuccessor() } //TODO: support capture of `this` in lambdas - class CapturedVariable instanceof S::CapturedDecl { + class CapturedVariable instanceof S::VarDecl { + CapturedVariable() { + any(S::CapturedDecl capturedDecl).getDecl() = this and + exists(this.getEnclosingCallable()) + } + string toString() { result = super.toString() } - Callable getCallable() { result = super.getScope() } + Callable getCallable() { result = super.getEnclosingCallable() } Location getLocation() { result = super.getLocation() } } - class CapturedParameter extends CapturedVariable { - CapturedParameter() { this.(S::CapturedDecl).getDecl() instanceof S::ParamDecl } - } + class CapturedParameter extends CapturedVariable instanceof S::ParamDecl { } class Expr instanceof S::AstNode { string toString() { result = super.toString() } @@ -762,23 +765,16 @@ private module CaptureInput implements VariableCapture::InputSig { Expr source; VariableWrite() { - exists(S::VarDecl varDecl | - variable.(S::CapturedDecl).getDecl() = varDecl and - variable.getCallable() = this.(S::AstNode).getEnclosingCallable() - | - exists(S::Assignment a | this = a | - a.getDest().(DeclRefExpr).getDecl() = varDecl and - source = a.getSource() - ) - or - exists(S::PatternBindingDecl pbd, S::NamedPattern np | - this = pbd and pbd.getAPattern() = np - | - np.getVarDecl() = varDecl and - source = np.getMatchingExpr() - ) - // TODO: support multiple variables in LHS of =, in both of above cases. + exists(S::Assignment a | this = a | + a.getDest().(DeclRefExpr).getDecl() = variable and + source = a.getSource() + ) + or + exists(S::PatternBindingDecl pbd, S::NamedPattern np | this = pbd and pbd.getAPattern() = np | + np.getVarDecl() = variable and + source = np.getMatchingExpr() ) + // TODO: support multiple variables in LHS of =, in both of above cases. } CapturedVariable getVariable() { result = variable } @@ -789,7 +785,7 @@ private module CaptureInput implements VariableCapture::InputSig { class VariableRead extends Expr instanceof S::DeclRefExpr { CapturedVariable v; - VariableRead() { this.getCapturedDecl() = v /* TODO: this should be an R-value only. */ } + VariableRead() { this.getDecl() = v /* TODO: this should be an R-value only. */ } CapturedVariable getVariable() { result = v } } @@ -818,7 +814,7 @@ private CaptureFlow::ClosureNode asClosureNode(Node n) { result.(CaptureFlow::ExprNode).getExpr() = n.asExpr() or result.(CaptureFlow::ExprPostUpdateNode).getExpr() = n.(PostUpdateNode).getPreUpdateNode().asExpr() or - result.(CaptureFlow::ParameterNode).getParameter().(CapturedDecl).getDecl() = n.getParameter() or + result.(CaptureFlow::ParameterNode).getParameter() = n.getParameter() or result.(CaptureFlow::ThisParameterNode).getCallable().getSelfParam() = n.getParameter() or result.(CaptureFlow::MallocNode).getClosureExpr() = n.getCfgNode().getNode().asAstNode() // TODO: figure out why the java version had PostUpdateNode logic here } diff --git a/swift/ql/test/library-tests/dataflow/capture/closures.swift b/swift/ql/test/library-tests/dataflow/capture/closures.swift index cb99f9fbbd5e..d72a337973b7 100644 --- a/swift/ql/test/library-tests/dataflow/capture/closures.swift +++ b/swift/ql/test/library-tests/dataflow/capture/closures.swift @@ -15,6 +15,17 @@ func captureList() { }() } +func setAndCallEscape() { + let x = source("setAndCallEscape", 0) + + let escape = { + sink(x) // $ MISSING: hasValueFlow=setAndCallEscape + return x + 1 + } + + sink(escape()) // $ MISSING: hasTaintFlow=setAndCallEscape +} + var escape: (() -> Int)? = nil func setEscape() { @@ -132,7 +143,7 @@ func taintCollections(array: inout Array) { array.withContiguousStorageIfAvailable({ buffer in sink(array) - sink(array[0]) // $ hasValueFlow=array + sink(array[0]) // $ MISSING: hasValueFlow=array }) } diff --git a/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected b/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected index 2d86d30449f3..ec17df2b76d1 100644 --- a/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected +++ b/swift/ql/test/library-tests/dataflow/capture/partialflowtest.expected @@ -14,216 +14,243 @@ | closures.swift:11:23:11:23 | captureList | closures.swift:11:7:11:10 | ... as ... | | closures.swift:11:23:11:23 | captureList | closures.swift:11:16:11:41 | call to source(_:_:) | | closures.swift:11:23:11:23 | captureList | closures.swift:11:38:11:38 | 123 | -| closures.swift:21:18:21:18 | setEscape | closures.swift:2:16:2:25 | label | -| closures.swift:21:18:21:18 | setEscape | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:21:18:21:18 | setEscape | closures.swift:2:33:2:42 | value | -| closures.swift:21:18:21:18 | setEscape | closures.swift:2:59:2:59 | value | -| closures.swift:21:18:21:18 | setEscape | closures.swift:21:7:21:7 | x | -| closures.swift:21:18:21:18 | setEscape | closures.swift:21:11:21:32 | call to source(_:_:) | -| closures.swift:21:18:21:18 | setEscape | closures.swift:21:31:21:31 | 0 | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:14:1:23 | value [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:34:1:43 | [...] [Array element] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value | -| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:1:43:1:43 | value [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:16:2:25 | label | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:33:2:42 | value [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value | -| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:2:59:2:59 | value [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | SSA def(x) [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:34:30:34:30 | x [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x | -| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:35:10:35:10 | x [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x | -| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:36:12:36:12 | x [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | SSA def(x) [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:7 | x [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:7:39:13 | ... as ... [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) | -| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:17:39:37 | call to source(_:_:) [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 | -| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:39:35:39:35 | 42 [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x | -| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:41:11:41:11 | x [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:17 | x [some:0] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0, ... (2)] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0, ... (3)] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0, ... (4)] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0, ... (5)] | -| closures.swift:39:24:39:24 | logical | closures.swift:42:17:42:18 | ...! [some:0] | -| closures.swift:52:50:52:50 | asyncTest | closures.swift:2:16:2:25 | label | -| closures.swift:52:50:52:50 | asyncTest | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:52:50:52:50 | asyncTest | closures.swift:2:33:2:42 | value | -| closures.swift:52:50:52:50 | asyncTest | closures.swift:2:59:2:59 | value | -| closures.swift:52:50:52:50 | asyncTest | closures.swift:48:18:48:23 | SSA def(x) | -| closures.swift:52:50:52:50 | asyncTest | closures.swift:48:18:48:23 | x | -| closures.swift:52:50:52:50 | asyncTest | closures.swift:49:29:49:29 | x | -| closures.swift:52:50:52:50 | asyncTest | closures.swift:52:43:52:65 | call to source(_:_:) | -| closures.swift:52:50:52:50 | asyncTest | closures.swift:52:63:52:63 | 40 | -| closures.swift:63:14:63:14 | foo | closures.swift:2:16:2:25 | label | -| closures.swift:63:14:63:14 | foo | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:63:14:63:14 | foo | closures.swift:2:33:2:42 | value | -| closures.swift:63:14:63:14 | foo | closures.swift:2:59:2:59 | value | -| closures.swift:63:14:63:14 | foo | closures.swift:63:7:63:23 | call to source(_:_:) | -| closures.swift:63:14:63:14 | foo | closures.swift:63:21:63:21 | 41 | -| closures.swift:73:14:73:14 | bar | closures.swift:2:16:2:25 | label | -| closures.swift:73:14:73:14 | bar | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:73:14:73:14 | bar | closures.swift:2:33:2:42 | value | -| closures.swift:73:14:73:14 | bar | closures.swift:2:59:2:59 | value | -| closures.swift:73:14:73:14 | bar | closures.swift:73:7:73:23 | call to source(_:_:) | -| closures.swift:73:14:73:14 | bar | closures.swift:73:21:73:21 | 41 | -| closures.swift:83:14:83:14 | baz | closures.swift:2:16:2:25 | label | -| closures.swift:83:14:83:14 | baz | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:83:14:83:14 | baz | closures.swift:2:33:2:42 | value | -| closures.swift:83:14:83:14 | baz | closures.swift:2:59:2:59 | value | -| closures.swift:83:14:83:14 | baz | closures.swift:83:7:83:23 | call to source(_:_:) | -| closures.swift:83:14:83:14 | baz | closures.swift:83:21:83:21 | 41 | -| closures.swift:91:20:91:20 | sharedCapture | closures.swift:2:16:2:25 | label | -| closures.swift:91:20:91:20 | sharedCapture | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:91:20:91:20 | sharedCapture | closures.swift:2:33:2:42 | value | -| closures.swift:91:20:91:20 | sharedCapture | closures.swift:2:59:2:59 | value | -| closures.swift:91:20:91:20 | sharedCapture | closures.swift:91:9:91:9 | x | -| closures.swift:91:20:91:20 | sharedCapture | closures.swift:91:13:91:38 | call to source(_:_:) | -| closures.swift:91:20:91:20 | sharedCapture | closures.swift:91:37:91:37 | 0 | -| closures.swift:118:35:118:35 | setter1 | closures.swift:2:16:2:25 | label | -| closures.swift:118:35:118:35 | setter1 | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:118:35:118:35 | setter1 | closures.swift:2:33:2:42 | value | -| closures.swift:118:35:118:35 | setter1 | closures.swift:2:59:2:59 | value | -| closures.swift:118:35:118:35 | setter1 | closures.swift:113:22:113:22 | y | -| closures.swift:118:35:118:35 | setter1 | closures.swift:118:28:118:47 | call to source(_:_:) | -| closures.swift:118:35:118:35 | setter1 | closures.swift:118:46:118:46 | 1 | -| closures.swift:119:35:119:35 | setter2 | closures.swift:2:16:2:25 | label | -| closures.swift:119:35:119:35 | setter2 | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:119:35:119:35 | setter2 | closures.swift:2:33:2:42 | value | -| closures.swift:119:35:119:35 | setter2 | closures.swift:2:59:2:59 | value | -| closures.swift:119:35:119:35 | setter2 | closures.swift:113:22:113:22 | y | -| closures.swift:119:35:119:35 | setter2 | closures.swift:119:28:119:47 | call to source(_:_:) | -| closures.swift:119:35:119:35 | setter2 | closures.swift:119:46:119:46 | 2 | -| closures.swift:129:21:129:21 | array | closures.swift:1:14:1:23 | SSA def(value) | -| closures.swift:129:21:129:21 | array | closures.swift:1:14:1:23 | SSA def(value) [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:1:14:1:23 | value | -| closures.swift:129:21:129:21 | array | closures.swift:1:14:1:23 | value [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:1:34:1:43 | [...] [Array element, ... (2)] | -| closures.swift:129:21:129:21 | array | closures.swift:1:34:1:43 | [...] [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:1:43:1:43 | value | -| closures.swift:129:21:129:21 | array | closures.swift:1:43:1:43 | value [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:2:16:2:25 | label | -| closures.swift:129:21:129:21 | array | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:129:21:129:21 | array | closures.swift:2:33:2:42 | value | -| closures.swift:129:21:129:21 | array | closures.swift:2:59:2:59 | value | -| closures.swift:129:21:129:21 | array | closures.swift:128:1:137:1 | array[return] [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:129:3:129:3 | &... [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:129:3:129:3 | [post] array [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:129:14:129:31 | call to source(_:_:) | -| closures.swift:129:21:129:21 | array | closures.swift:129:30:129:30 | 0 | -| closures.swift:129:21:129:21 | array | closures.swift:130:8:130:8 | array [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:131:8:131:8 | &... [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:131:8:131:8 | array [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:131:8:131:15 | ...[...] | -| closures.swift:129:21:129:21 | array | closures.swift:132:3:132:3 | array [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:133:5:133:5 | buffer [Collection element] | -| closures.swift:129:21:129:21 | array | closures.swift:134:10:134:10 | array [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:135:10:135:10 | &... [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:135:10:135:10 | array [Array element] | -| closures.swift:129:21:129:21 | array | closures.swift:135:10:135:17 | ...[...] | -| closures.swift:129:21:129:21 | array | file://:0:0:0:0 | [summary param] this in withContiguousStorageIfAvailable(_:) [Array element] | -| closures.swift:129:21:129:21 | array | file://:0:0:0:0 | [summary] read: Argument[this].ArrayElement in withContiguousStorageIfAvailable(_:) | -| closures.swift:129:21:129:21 | array | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in withContiguousStorageIfAvailable(_:) [Collection element] | -| closures.swift:129:21:129:21 | array | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0].CollectionElement in withContiguousStorageIfAvailable(_:) | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:1:14:1:23 | SSA def(value) | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:1:14:1:23 | value | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:1:34:1:43 | [...] [Array element] | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:1:43:1:43 | value | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:2:16:2:25 | label | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:2:33:2:42 | SSA def(value) | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:2:33:2:42 | value | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:2:59:2:59 | value | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:140:7:140:7 | SSA def(x) | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:140:7:140:7 | x | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:140:11:140:35 | call to source(_:_:) | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:140:34:140:34 | 0 | -| closures.swift:140:18:140:18 | simplestTest | closures.swift:141:8:141:8 | x | +| closures.swift:19:18:19:18 | setAndCallEscape | closures.swift:2:16:2:25 | label | +| closures.swift:19:18:19:18 | setAndCallEscape | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:19:18:19:18 | setAndCallEscape | closures.swift:2:33:2:42 | value | +| closures.swift:19:18:19:18 | setAndCallEscape | closures.swift:2:59:2:59 | value | +| closures.swift:19:18:19:18 | setAndCallEscape | closures.swift:19:7:19:7 | x | +| closures.swift:19:18:19:18 | setAndCallEscape | closures.swift:19:11:19:39 | call to source(_:_:) | +| closures.swift:19:18:19:18 | setAndCallEscape | closures.swift:19:38:19:38 | 0 | +| closures.swift:32:18:32:18 | setEscape | closures.swift:2:16:2:25 | label | +| closures.swift:32:18:32:18 | setEscape | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:32:18:32:18 | setEscape | closures.swift:2:33:2:42 | value | +| closures.swift:32:18:32:18 | setEscape | closures.swift:2:59:2:59 | value | +| closures.swift:32:18:32:18 | setEscape | closures.swift:32:7:32:7 | x | +| closures.swift:32:18:32:18 | setEscape | closures.swift:32:11:32:32 | call to source(_:_:) | +| closures.swift:32:18:32:18 | setEscape | closures.swift:32:31:32:31 | 0 | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | SSA def(value) | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | SSA def(value) [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | value | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | value [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:14:1:23 | value [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:34:1:43 | [...] [Array element, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:34:1:43 | [...] [Array element] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:43:1:43 | value | +| closures.swift:50:24:50:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:43:1:43 | value [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:1:43:1:43 | value [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:16:2:25 | label | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | SSA def(value) [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | value | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | value [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:33:2:42 | value [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:59:2:59 | value | +| closures.swift:50:24:50:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:59:2:59 | value [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:2:59:2:59 | value [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | SSA def(x) | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | SSA def(x) [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | SSA def(x) [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | SSA def(x) [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | SSA def(x) [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | SSA def(x) [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | x | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | x [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | x [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | x [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | x [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:45:30:45:30 | x [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:46:10:46:10 | x | +| closures.swift:50:24:50:24 | logical | closures.swift:46:10:46:10 | x [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:46:10:46:10 | x [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:46:10:46:10 | x [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:46:10:46:10 | x [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:46:10:46:10 | x [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:47:12:47:12 | x | +| closures.swift:50:24:50:24 | logical | closures.swift:47:12:47:12 | x [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:47:12:47:12 | x [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:47:12:47:12 | x [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:47:12:47:12 | x [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:47:12:47:12 | x [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | SSA def(x) | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | SSA def(x) [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | SSA def(x) [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | SSA def(x) [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | SSA def(x) [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | SSA def(x) [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | x | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | x [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | x [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | x [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | x [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:7 | x [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:13 | ... as ... | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:13 | ... as ... [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:13 | ... as ... [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:13 | ... as ... [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:13 | ... as ... [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:7:50:13 | ... as ... [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:17:50:37 | call to source(_:_:) | +| closures.swift:50:24:50:24 | logical | closures.swift:50:17:50:37 | call to source(_:_:) [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:17:50:37 | call to source(_:_:) [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:17:50:37 | call to source(_:_:) [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:17:50:37 | call to source(_:_:) [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:17:50:37 | call to source(_:_:) [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:35:50:35 | 42 | +| closures.swift:50:24:50:24 | logical | closures.swift:50:35:50:35 | 42 [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:35:50:35 | 42 [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:35:50:35 | 42 [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:35:50:35 | 42 [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:50:35:50:35 | 42 [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:52:11:52:11 | x | +| closures.swift:50:24:50:24 | logical | closures.swift:52:11:52:11 | x [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:52:11:52:11 | x [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:52:11:52:11 | x [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:52:11:52:11 | x [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:52:11:52:11 | x [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:17 | x | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:17 | x [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:17 | x [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:17 | x [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:17 | x [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:17 | x [some:0] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:18 | ...! | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:18 | ...! [some:0, ... (2)] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:18 | ...! [some:0, ... (3)] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:18 | ...! [some:0, ... (4)] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:18 | ...! [some:0, ... (5)] | +| closures.swift:50:24:50:24 | logical | closures.swift:53:17:53:18 | ...! [some:0] | +| closures.swift:63:50:63:50 | asyncTest | closures.swift:2:16:2:25 | label | +| closures.swift:63:50:63:50 | asyncTest | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:63:50:63:50 | asyncTest | closures.swift:2:33:2:42 | value | +| closures.swift:63:50:63:50 | asyncTest | closures.swift:2:59:2:59 | value | +| closures.swift:63:50:63:50 | asyncTest | closures.swift:59:18:59:23 | SSA def(x) | +| closures.swift:63:50:63:50 | asyncTest | closures.swift:59:18:59:23 | x | +| closures.swift:63:50:63:50 | asyncTest | closures.swift:60:29:60:29 | x | +| closures.swift:63:50:63:50 | asyncTest | closures.swift:63:43:63:65 | call to source(_:_:) | +| closures.swift:63:50:63:50 | asyncTest | closures.swift:63:63:63:63 | 40 | +| closures.swift:74:14:74:14 | foo | closures.swift:2:16:2:25 | label | +| closures.swift:74:14:74:14 | foo | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:74:14:74:14 | foo | closures.swift:2:33:2:42 | value | +| closures.swift:74:14:74:14 | foo | closures.swift:2:59:2:59 | value | +| closures.swift:74:14:74:14 | foo | closures.swift:74:7:74:23 | call to source(_:_:) | +| closures.swift:74:14:74:14 | foo | closures.swift:74:21:74:21 | 41 | +| closures.swift:84:14:84:14 | bar | closures.swift:2:16:2:25 | label | +| closures.swift:84:14:84:14 | bar | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:84:14:84:14 | bar | closures.swift:2:33:2:42 | value | +| closures.swift:84:14:84:14 | bar | closures.swift:2:59:2:59 | value | +| closures.swift:84:14:84:14 | bar | closures.swift:84:7:84:23 | call to source(_:_:) | +| closures.swift:84:14:84:14 | bar | closures.swift:84:21:84:21 | 41 | +| closures.swift:94:14:94:14 | baz | closures.swift:2:16:2:25 | label | +| closures.swift:94:14:94:14 | baz | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:94:14:94:14 | baz | closures.swift:2:33:2:42 | value | +| closures.swift:94:14:94:14 | baz | closures.swift:2:59:2:59 | value | +| closures.swift:94:14:94:14 | baz | closures.swift:94:7:94:23 | call to source(_:_:) | +| closures.swift:94:14:94:14 | baz | closures.swift:94:21:94:21 | 41 | +| closures.swift:102:20:102:20 | sharedCapture | closures.swift:2:16:2:25 | label | +| closures.swift:102:20:102:20 | sharedCapture | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:102:20:102:20 | sharedCapture | closures.swift:2:33:2:42 | value | +| closures.swift:102:20:102:20 | sharedCapture | closures.swift:2:59:2:59 | value | +| closures.swift:102:20:102:20 | sharedCapture | closures.swift:102:9:102:9 | x | +| closures.swift:102:20:102:20 | sharedCapture | closures.swift:102:13:102:38 | call to source(_:_:) | +| closures.swift:102:20:102:20 | sharedCapture | closures.swift:102:37:102:37 | 0 | +| closures.swift:129:35:129:35 | setter1 | closures.swift:2:16:2:25 | label | +| closures.swift:129:35:129:35 | setter1 | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:129:35:129:35 | setter1 | closures.swift:2:33:2:42 | value | +| closures.swift:129:35:129:35 | setter1 | closures.swift:2:59:2:59 | value | +| closures.swift:129:35:129:35 | setter1 | closures.swift:124:22:124:22 | y | +| closures.swift:129:35:129:35 | setter1 | closures.swift:125:9:125:9 | SSA def(setter) [y] | +| closures.swift:129:35:129:35 | setter1 | closures.swift:125:9:125:9 | setter [y] | +| closures.swift:129:35:129:35 | setter1 | closures.swift:125:18:125:26 | y | +| closures.swift:129:35:129:35 | setter1 | closures.swift:125:18:125:26 | { ... } [y] | +| closures.swift:129:35:129:35 | setter1 | closures.swift:126:12:126:12 | setter [y] | +| closures.swift:129:35:129:35 | setter1 | closures.swift:129:7:129:7 | SSA def(setter1) [y] | +| closures.swift:129:35:129:35 | setter1 | closures.swift:129:7:129:7 | setter1 [y] | +| closures.swift:129:35:129:35 | setter1 | closures.swift:129:17:129:48 | call to ... [y] | +| closures.swift:129:35:129:35 | setter1 | closures.swift:129:28:129:47 | call to source(_:_:) | +| closures.swift:129:35:129:35 | setter1 | closures.swift:129:46:129:46 | 1 | +| closures.swift:129:35:129:35 | setter1 | closures.swift:132:3:132:3 | setter1 [y] | +| closures.swift:130:35:130:35 | setter2 | closures.swift:2:16:2:25 | label | +| closures.swift:130:35:130:35 | setter2 | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:130:35:130:35 | setter2 | closures.swift:2:33:2:42 | value | +| closures.swift:130:35:130:35 | setter2 | closures.swift:2:59:2:59 | value | +| closures.swift:130:35:130:35 | setter2 | closures.swift:124:22:124:22 | y | +| closures.swift:130:35:130:35 | setter2 | closures.swift:125:9:125:9 | SSA def(setter) [y] | +| closures.swift:130:35:130:35 | setter2 | closures.swift:125:9:125:9 | setter [y] | +| closures.swift:130:35:130:35 | setter2 | closures.swift:125:18:125:26 | y | +| closures.swift:130:35:130:35 | setter2 | closures.swift:125:18:125:26 | { ... } [y] | +| closures.swift:130:35:130:35 | setter2 | closures.swift:126:12:126:12 | setter [y] | +| closures.swift:130:35:130:35 | setter2 | closures.swift:130:7:130:7 | SSA def(setter2) [y] | +| closures.swift:130:35:130:35 | setter2 | closures.swift:130:7:130:7 | setter2 [y] | +| closures.swift:130:35:130:35 | setter2 | closures.swift:130:17:130:48 | call to ... [y] | +| closures.swift:130:35:130:35 | setter2 | closures.swift:130:28:130:47 | call to source(_:_:) | +| closures.swift:130:35:130:35 | setter2 | closures.swift:130:46:130:46 | 2 | +| closures.swift:130:35:130:35 | setter2 | closures.swift:135:3:135:3 | setter2 [y] | +| closures.swift:140:21:140:21 | array | closures.swift:1:14:1:23 | SSA def(value) | +| closures.swift:140:21:140:21 | array | closures.swift:1:14:1:23 | SSA def(value) [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:1:14:1:23 | value | +| closures.swift:140:21:140:21 | array | closures.swift:1:14:1:23 | value [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:1:34:1:43 | [...] [Array element, ... (2)] | +| closures.swift:140:21:140:21 | array | closures.swift:1:34:1:43 | [...] [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:1:43:1:43 | value | +| closures.swift:140:21:140:21 | array | closures.swift:1:43:1:43 | value [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:2:16:2:25 | label | +| closures.swift:140:21:140:21 | array | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:140:21:140:21 | array | closures.swift:2:33:2:42 | value | +| closures.swift:140:21:140:21 | array | closures.swift:2:59:2:59 | value | +| closures.swift:140:21:140:21 | array | closures.swift:139:1:148:1 | array[return] [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:140:3:140:3 | &... [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:140:3:140:3 | [post] array [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:140:3:140:3 | array [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:140:3:140:10 | ...[...] | +| closures.swift:140:21:140:21 | array | closures.swift:140:14:140:31 | call to source(_:_:) | +| closures.swift:140:21:140:21 | array | closures.swift:140:30:140:30 | 0 | +| closures.swift:140:21:140:21 | array | closures.swift:141:8:141:8 | array [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:142:8:142:8 | &... [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:142:8:142:8 | array [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:142:8:142:15 | ...[...] | +| closures.swift:140:21:140:21 | array | closures.swift:143:3:143:3 | array [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:143:42:147:3 | array [Array element] | +| closures.swift:140:21:140:21 | array | closures.swift:143:42:147:3 | { ... } [array, ... (2)] | +| closures.swift:140:21:140:21 | array | closures.swift:144:5:144:5 | buffer [Collection element] | +| closures.swift:140:21:140:21 | array | file://:0:0:0:0 | [summary param] 0 in withContiguousStorageIfAvailable(_:) [array, ... (2)] | +| closures.swift:140:21:140:21 | array | file://:0:0:0:0 | [summary param] this in withContiguousStorageIfAvailable(_:) [Array element] | +| closures.swift:140:21:140:21 | array | file://:0:0:0:0 | [summary] read: Argument[this].ArrayElement in withContiguousStorageIfAvailable(_:) | +| closures.swift:140:21:140:21 | array | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in withContiguousStorageIfAvailable(_:) [Collection element] | +| closures.swift:140:21:140:21 | array | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0].CollectionElement in withContiguousStorageIfAvailable(_:) | +| closures.swift:140:21:140:21 | array | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[this] in withContiguousStorageIfAvailable(_:) [array, ... (2)] | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:1:14:1:23 | SSA def(value) | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:1:14:1:23 | value | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:1:34:1:43 | [...] [Array element] | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:1:43:1:43 | value | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:2:16:2:25 | label | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:2:33:2:42 | SSA def(value) | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:2:33:2:42 | value | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:2:59:2:59 | value | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:151:7:151:7 | SSA def(x) | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:151:7:151:7 | x | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:151:11:151:35 | call to source(_:_:) | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:151:34:151:34 | 0 | +| closures.swift:151:18:151:18 | simplestTest | closures.swift:152:8:152:8 | x | From fe7e18ef39023c50720d274c2271cbad2fa39cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Mon, 25 Sep 2023 18:50:41 +0200 Subject: [PATCH 13/13] Swift: add CapturePostUpdateNode However, this doesn't change any of the test results. --- .../swift/dataflow/internal/DataFlowPrivate.qll | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index afcd6e1def72..b7992116705c 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -1140,6 +1140,17 @@ private module PostUpdateNodes { result.(FlowSummaryNode).getSummaryNode()) } } + + class CapturePostUpdateNode extends PostUpdateNodeImpl, CaptureNode { + private CaptureNode pre; + + CapturePostUpdateNode() { + CaptureFlow::capturePostUpdateNode(this.getSynthesizedCaptureNode(), + pre.getSynthesizedCaptureNode()) + } + + override Node getPreUpdateNode() { result = pre } + } } private import PostUpdateNodes