From 31378970c2d5b87e9ed048e2a0839b31f89ded65 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 11:29:22 +0200 Subject: [PATCH 01/40] unified: Add test showing spurious SSA flow --- .../ql/test/library-tests/dataflow/test.expected | 16 ++++++++++++++++ .../ql/test/library-tests/dataflow/test.swift | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/unified/ql/test/library-tests/dataflow/test.expected b/unified/ql/test/library-tests/dataflow/test.expected index 7ae6ed5e6691..9ec3c9eb2890 100644 --- a/unified/ql/test/library-tests/dataflow/test.expected +++ b/unified/ql/test/library-tests/dataflow/test.expected @@ -178,6 +178,12 @@ edges | test.swift:175:25:175:39 | source(...) | test.swift:175:15:175:39 | ... + ... | provenance | | | test.swift:175:42:175:66 | ... + ... | test.swift:175:14:175:67 | TupleExpr [1] | provenance | | | test.swift:175:52:175:66 | source(...) | test.swift:175:42:175:66 | ... + ... | provenance | | +| test.swift:182:9:182:9 | x | test.swift:185:10:185:10 | x | provenance | | +| test.swift:182:9:182:9 | x | test.swift:186:10:186:10 | y | provenance | | +| test.swift:182:13:182:27 | source(...) | test.swift:182:9:182:9 | x | provenance | | +| test.swift:183:9:183:9 | y | test.swift:185:10:185:10 | x | provenance | | +| test.swift:183:9:183:9 | y | test.swift:186:10:186:10 | y | provenance | | +| test.swift:183:13:183:27 | source(...) | test.swift:183:9:183:9 | y | provenance | | nodes | calls.swift:7:19:7:19 | x | semmle.label | x | | calls.swift:8:14:8:14 | x | semmle.label | x | @@ -407,6 +413,12 @@ nodes | test.swift:175:52:175:66 | source(...) | semmle.label | source(...) | | test.swift:176:10:176:10 | a | semmle.label | a | | test.swift:177:10:177:10 | b | semmle.label | b | +| test.swift:182:9:182:9 | x | semmle.label | x | +| test.swift:182:13:182:27 | source(...) | semmle.label | source(...) | +| test.swift:183:9:183:9 | y | semmle.label | y | +| test.swift:183:13:183:27 | source(...) | semmle.label | source(...) | +| test.swift:185:10:185:10 | x | semmle.label | x | +| test.swift:186:10:186:10 | y | semmle.label | y | subpaths | calls.swift:31:17:31:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:31:10:31:31 | target(...) | | calls.swift:32:17:32:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:32:10:32:31 | target(...) | @@ -476,3 +488,7 @@ testFailures | test.swift:168:10:168:12 | ... .0 | test.swift:167:29:167:43 | source(...) | test.swift:168:10:168:12 | ... .0 | $@ | test.swift:167:29:167:43 | source(...) | source(...) | | test.swift:176:10:176:10 | a | test.swift:175:25:175:39 | source(...) | test.swift:176:10:176:10 | a | $@ | test.swift:175:25:175:39 | source(...) | source(...) | | test.swift:177:10:177:10 | b | test.swift:175:52:175:66 | source(...) | test.swift:177:10:177:10 | b | $@ | test.swift:175:52:175:66 | source(...) | source(...) | +| test.swift:185:10:185:10 | x | test.swift:182:13:182:27 | source(...) | test.swift:185:10:185:10 | x | $@ | test.swift:182:13:182:27 | source(...) | source(...) | +| test.swift:185:10:185:10 | x | test.swift:183:13:183:27 | source(...) | test.swift:185:10:185:10 | x | $@ | test.swift:183:13:183:27 | source(...) | source(...) | +| test.swift:186:10:186:10 | y | test.swift:182:13:182:27 | source(...) | test.swift:186:10:186:10 | y | $@ | test.swift:182:13:182:27 | source(...) | source(...) | +| test.swift:186:10:186:10 | y | test.swift:183:13:183:27 | source(...) | test.swift:186:10:186:10 | y | $@ | test.swift:183:13:183:27 | source(...) | source(...) | diff --git a/unified/ql/test/library-tests/dataflow/test.swift b/unified/ql/test/library-tests/dataflow/test.swift index a7fa42ee6100..36c3babdf8de 100644 --- a/unified/ql/test/library-tests/dataflow/test.swift +++ b/unified/ql/test/library-tests/dataflow/test.swift @@ -176,3 +176,12 @@ func t19() { sink(a) // $ hasTaintFlow=t19.1 sink(b) // $ hasTaintFlow=t19.2 } + +func t20() { + func foo(x: String, y: String) -> String { return x } + var x = source("t20.1") + var y = source("t20.2") + foo(x: x, y: y) + sink(x) // $ hasValueFlow=t20.1 SPURIOUS: hasValueFlow=t20.2 + sink(y) // $ hasValueFlow=t20.2 SPURIOUS: hasValueFlow=t20.1 +} From f906f8dc55fd7509092e5b042a20efac07871c40 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 11:51:36 +0200 Subject: [PATCH 02/40] Ssa: Add consistency check for ambiguous read --- shared/ssa/codeql/ssa/Ssa.qll | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/shared/ssa/codeql/ssa/Ssa.qll b/shared/ssa/codeql/ssa/Ssa.qll index a0c295c5d27d..151728da5466 100644 --- a/shared/ssa/codeql/ssa/Ssa.qll +++ b/shared/ssa/codeql/ssa/Ssa.qll @@ -2144,6 +2144,17 @@ module Make< ) } } + + /** Provides consistency checks that depend on the DataFlowIntegration inputs. */ + module DfConsistency { + /** + * The given `read` reads multiple variables at once. `var` is bound to one of them. + */ + query predicate ambiguousReadNode(ReadNode read, SourceVariable var) { + strictcount(SourceVariable v | read.readsAt(_, _, v)) > 1 and + read.readsAt(_, _, var) + } + } } /** From 9d8f5e615a2583bd28f753affb10242c45267e36 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 11:59:58 +0200 Subject: [PATCH 03/40] unified: Add consistency check --- .../LocalSsaConsistency.ql | 1 + .../CONSISTENCY/LocalSsaConsistency.expected | 25 ++ .../CONSISTENCY/LocalSsaConsistency.expected | 5 + .../CONSISTENCY/LocalSsaConsistency.expected | 0 .../CONSISTENCY/LocalSsaConsistency.expected | 5 + .../CONSISTENCY/LocalSsaConsistency.expected | 18 + .../CONSISTENCY/LocalSsaConsistency.expected | 41 +++ .../CONSISTENCY/LocalSsaConsistency.expected | 347 ++++++++++++++++++ 8 files changed, 442 insertions(+) create mode 100644 unified/ql/test/library-tests/BasicTest/CONSISTENCY/LocalSsaConsistency.expected create mode 100644 unified/ql/test/library-tests/constructors/CONSISTENCY/LocalSsaConsistency.expected create mode 100644 unified/ql/test/library-tests/controlflow/CONSISTENCY/LocalSsaConsistency.expected create mode 100644 unified/ql/test/library-tests/dataflow/CONSISTENCY/LocalSsaConsistency.expected create mode 100644 unified/ql/test/library-tests/mad/CONSISTENCY/LocalSsaConsistency.expected create mode 100644 unified/ql/test/library-tests/type-inference/CONSISTENCY/LocalSsaConsistency.expected create mode 100644 unified/ql/test/query-tests/security/CWE-022/PathInjection/CONSISTENCY/LocalSsaConsistency.expected diff --git a/unified/ql/consistency-queries/LocalSsaConsistency.ql b/unified/ql/consistency-queries/LocalSsaConsistency.ql index 209adfca340a..ca0d9550ad20 100644 --- a/unified/ql/consistency-queries/LocalSsaConsistency.ql +++ b/unified/ql/consistency-queries/LocalSsaConsistency.ql @@ -1,3 +1,4 @@ private import unified private import codeql.unified.internal.dataflow.LocalSsa import LocalSsaOutput::Consistency +import LocalSsaDataFlowOutput::DfConsistency diff --git a/unified/ql/test/library-tests/BasicTest/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/BasicTest/CONSISTENCY/LocalSsaConsistency.expected new file mode 100644 index 000000000000..32f5189788a0 --- /dev/null +++ b/unified/ql/test/library-tests/BasicTest/CONSISTENCY/LocalSsaConsistency.expected @@ -0,0 +1,25 @@ +ambiguousReadNode +| test.swift:8:9:8:26 | [variable post-update] item | test.swift:7:5:9:5 | self | +| test.swift:8:9:8:26 | [variable post-update] item | test.swift:7:25:7:28 | item | +| test.swift:8:9:8:26 | [variable post-update] self | test.swift:7:5:9:5 | self | +| test.swift:8:9:8:26 | [variable post-update] self | test.swift:7:25:7:28 | item | +| test.swift:12:16:12:35 | [variable post-update] item | test.swift:11:5:13:5 | self | +| test.swift:12:16:12:35 | [variable post-update] item | test.swift:11:21:11:24 | item | +| test.swift:12:16:12:35 | [variable post-update] self | test.swift:11:5:13:5 | self | +| test.swift:12:16:12:35 | [variable post-update] self | test.swift:11:21:11:24 | item | +| test.swift:27:13:27:33 | [variable post-update] item | test.swift:25:9:25:14 | result | +| test.swift:27:13:27:33 | [variable post-update] item | test.swift:26:9:26:12 | item | +| test.swift:27:13:27:33 | [variable post-update] result | test.swift:25:9:25:14 | result | +| test.swift:27:13:27:33 | [variable post-update] result | test.swift:26:9:26:12 | item | +| test.swift:28:13:28:31 | [variable post-update] item | test.swift:25:9:25:14 | result | +| test.swift:28:13:28:31 | [variable post-update] item | test.swift:26:9:26:12 | item | +| test.swift:28:13:28:31 | [variable post-update] result | test.swift:25:9:25:14 | result | +| test.swift:28:13:28:31 | [variable post-update] result | test.swift:26:9:26:12 | item | +| test.swift:49:16:49:26 | [variable post-update] index | test.swift:47:5:50:5 | self | +| test.swift:49:16:49:26 | [variable post-update] index | test.swift:47:18:47:22 | index | +| test.swift:49:16:49:26 | [variable post-update] self | test.swift:47:5:50:5 | self | +| test.swift:49:16:49:26 | [variable post-update] self | test.swift:47:18:47:22 | index | +| test.swift:53:9:53:25 | [variable post-update] item | test.swift:52:5:54:5 | self | +| test.swift:53:9:53:25 | [variable post-update] item | test.swift:52:16:52:19 | item | +| test.swift:53:9:53:25 | [variable post-update] self | test.swift:52:5:54:5 | self | +| test.swift:53:9:53:25 | [variable post-update] self | test.swift:52:16:52:19 | item | diff --git a/unified/ql/test/library-tests/constructors/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/constructors/CONSISTENCY/LocalSsaConsistency.expected new file mode 100644 index 000000000000..bbb75f55a047 --- /dev/null +++ b/unified/ql/test/library-tests/constructors/CONSISTENCY/LocalSsaConsistency.expected @@ -0,0 +1,5 @@ +ambiguousReadNode +| constructors.swift:35:9:35:29 | [variable post-update] self | constructors.swift:34:5:36:5 | self | +| constructors.swift:35:9:35:29 | [variable post-update] self | constructors.swift:34:22:34:22 | x | +| constructors.swift:35:9:35:29 | [variable post-update] x | constructors.swift:34:5:36:5 | self | +| constructors.swift:35:9:35:29 | [variable post-update] x | constructors.swift:34:22:34:22 | x | diff --git a/unified/ql/test/library-tests/controlflow/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/controlflow/CONSISTENCY/LocalSsaConsistency.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/unified/ql/test/library-tests/dataflow/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/dataflow/CONSISTENCY/LocalSsaConsistency.expected new file mode 100644 index 000000000000..cc9c71d9b150 --- /dev/null +++ b/unified/ql/test/library-tests/dataflow/CONSISTENCY/LocalSsaConsistency.expected @@ -0,0 +1,5 @@ +ambiguousReadNode +| test.swift:184:5:184:19 | [variable post-update] x | test.swift:182:9:182:9 | x | +| test.swift:184:5:184:19 | [variable post-update] x | test.swift:183:9:183:9 | y | +| test.swift:184:5:184:19 | [variable post-update] y | test.swift:182:9:182:9 | x | +| test.swift:184:5:184:19 | [variable post-update] y | test.swift:183:9:183:9 | y | diff --git a/unified/ql/test/library-tests/mad/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/mad/CONSISTENCY/LocalSsaConsistency.expected new file mode 100644 index 000000000000..6a0d83888e90 --- /dev/null +++ b/unified/ql/test/library-tests/mad/CONSISTENCY/LocalSsaConsistency.expected @@ -0,0 +1,18 @@ +ambiguousReadNode +| test.swift:74:9:84:31 | [variable post-update] encryptionKey | test.swift:67:5:67:17 | encryptionKey | +| test.swift:74:9:84:31 | [variable post-update] encryptionKey | test.swift:68:5:68:11 | fileURL | +| test.swift:74:9:84:31 | [variable post-update] fileURL | test.swift:67:5:67:17 | encryptionKey | +| test.swift:74:9:84:31 | [variable post-update] fileURL | test.swift:68:5:68:11 | fileURL | +| test.swift:86:9:96:31 | [variable post-update] encryptionKey | test.swift:67:5:67:17 | encryptionKey | +| test.swift:86:9:96:31 | [variable post-update] encryptionKey | test.swift:68:5:68:11 | fileURL | +| test.swift:86:9:96:31 | [variable post-update] fileURL | test.swift:67:5:67:17 | encryptionKey | +| test.swift:86:9:96:31 | [variable post-update] fileURL | test.swift:68:5:68:11 | fileURL | +| test.swift:98:9:109:31 | [variable post-update] encryptionKey | test.swift:67:5:67:17 | encryptionKey | +| test.swift:98:9:109:31 | [variable post-update] encryptionKey | test.swift:68:5:68:11 | fileURL | +| test.swift:98:9:109:31 | [variable post-update] encryptionKey | test.swift:69:5:69:16 | seedFilePath | +| test.swift:98:9:109:31 | [variable post-update] fileURL | test.swift:67:5:67:17 | encryptionKey | +| test.swift:98:9:109:31 | [variable post-update] fileURL | test.swift:68:5:68:11 | fileURL | +| test.swift:98:9:109:31 | [variable post-update] fileURL | test.swift:69:5:69:16 | seedFilePath | +| test.swift:98:9:109:31 | [variable post-update] seedFilePath | test.swift:67:5:67:17 | encryptionKey | +| test.swift:98:9:109:31 | [variable post-update] seedFilePath | test.swift:68:5:68:11 | fileURL | +| test.swift:98:9:109:31 | [variable post-update] seedFilePath | test.swift:69:5:69:16 | seedFilePath | diff --git a/unified/ql/test/library-tests/type-inference/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/type-inference/CONSISTENCY/LocalSsaConsistency.expected new file mode 100644 index 000000000000..b48e15341459 --- /dev/null +++ b/unified/ql/test/library-tests/type-inference/CONSISTENCY/LocalSsaConsistency.expected @@ -0,0 +1,41 @@ +ambiguousReadNode +| closures.swift:47:9:47:21 | [variable post-update] self | closures.swift:45:5:49:5 | self | +| closures.swift:47:9:47:21 | [variable post-update] self | closures.swift:45:24:45:28 | value | +| closures.swift:47:9:47:21 | [variable post-update] value | closures.swift:45:5:49:5 | self | +| closures.swift:47:9:47:21 | [variable post-update] value | closures.swift:45:24:45:28 | value | +| closures.swift:48:16:48:29 | [variable post-update] self | closures.swift:45:5:49:5 | self | +| closures.swift:48:16:48:29 | [variable post-update] self | closures.swift:45:24:45:28 | value | +| closures.swift:48:16:48:29 | [variable post-update] value | closures.swift:45:5:49:5 | self | +| closures.swift:48:16:48:29 | [variable post-update] value | closures.swift:45:24:45:28 | value | +| generics.swift:156:5:156:22 | [variable post-update] v1 | generics.swift:155:10:155:11 | v1 | +| generics.swift:156:5:156:22 | [variable post-update] v1 | generics.swift:155:20:155:21 | v2 | +| generics.swift:156:5:156:22 | [variable post-update] v2 | generics.swift:155:10:155:11 | v1 | +| generics.swift:156:5:156:22 | [variable post-update] v2 | generics.swift:155:20:155:21 | v2 | +| key_paths.swift:44:14:44:35 | [variable post-update] e | key_paths.swift:42:7:42:7 | s | +| key_paths.swift:44:14:44:35 | [variable post-update] e | key_paths.swift:43:7:43:7 | e | +| key_paths.swift:44:14:44:35 | [variable post-update] s | key_paths.swift:42:7:42:7 | s | +| key_paths.swift:44:14:44:35 | [variable post-update] s | key_paths.swift:43:7:43:7 | e | +| key_paths.swift:142:18:142:45 | [variable post-update] kpStart | key_paths.swift:140:7:140:13 | kpStart | +| key_paths.swift:142:18:142:45 | [variable post-update] kpStart | key_paths.swift:141:7:141:9 | kpX | +| key_paths.swift:142:18:142:45 | [variable post-update] kpX | key_paths.swift:140:7:140:13 | kpStart | +| key_paths.swift:142:18:142:45 | [variable post-update] kpX | key_paths.swift:141:7:141:9 | kpX | +| key_paths.swift:146:14:146:35 | [variable post-update] e | key_paths.swift:144:7:144:7 | s | +| key_paths.swift:146:14:146:35 | [variable post-update] e | key_paths.swift:145:7:145:7 | e | +| key_paths.swift:146:14:146:35 | [variable post-update] s | key_paths.swift:144:7:144:7 | s | +| key_paths.swift:146:14:146:35 | [variable post-update] s | key_paths.swift:145:7:145:7 | e | +| overload_resolution.swift:371:5:371:34 | [variable post-update] name | overload_resolution.swift:370:3:372:3 | self | +| overload_resolution.swift:371:5:371:34 | [variable post-update] name | overload_resolution.swift:370:20:370:23 | name | +| overload_resolution.swift:371:5:371:34 | [variable post-update] self | overload_resolution.swift:370:3:372:3 | self | +| overload_resolution.swift:371:5:371:34 | [variable post-update] self | overload_resolution.swift:370:20:370:23 | name | +| overload_resolution.swift:375:5:375:42 | [variable post-update] self | overload_resolution.swift:374:3:376:3 | self | +| overload_resolution.swift:375:5:375:42 | [variable post-update] self | overload_resolution.swift:374:20:374:23 | size | +| overload_resolution.swift:375:5:375:42 | [variable post-update] size | overload_resolution.swift:374:3:376:3 | self | +| overload_resolution.swift:375:5:375:42 | [variable post-update] size | overload_resolution.swift:374:20:374:23 | size | +| overload_resolution.swift:415:12:415:22 | [variable post-update] index | overload_resolution.swift:414:3:416:3 | self | +| overload_resolution.swift:415:12:415:22 | [variable post-update] index | overload_resolution.swift:414:14:414:18 | index | +| overload_resolution.swift:415:12:415:22 | [variable post-update] self | overload_resolution.swift:414:3:416:3 | self | +| overload_resolution.swift:415:12:415:22 | [variable post-update] self | overload_resolution.swift:414:14:414:18 | index | +| overload_resolution.swift:419:12:419:20 | [variable post-update] key | overload_resolution.swift:418:3:420:3 | self | +| overload_resolution.swift:419:12:419:20 | [variable post-update] key | overload_resolution.swift:418:14:418:16 | key | +| overload_resolution.swift:419:12:419:20 | [variable post-update] self | overload_resolution.swift:418:3:420:3 | self | +| overload_resolution.swift:419:12:419:20 | [variable post-update] self | overload_resolution.swift:418:14:418:16 | key | diff --git a/unified/ql/test/query-tests/security/CWE-022/PathInjection/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/query-tests/security/CWE-022/PathInjection/CONSISTENCY/LocalSsaConsistency.expected new file mode 100644 index 000000000000..173907e3ef5a --- /dev/null +++ b/unified/ql/test/query-tests/security/CWE-022/PathInjection/CONSISTENCY/LocalSsaConsistency.expected @@ -0,0 +1,347 @@ +ambiguousReadNode +| testPathInjection.swift:43:9:43:23 | [variable post-update] data | testPathInjection.swift:41:5:44:5 | self | +| testPathInjection.swift:43:9:43:23 | [variable post-update] data | testPathInjection.swift:42:13:42:16 | data | +| testPathInjection.swift:43:9:43:23 | [variable post-update] self | testPathInjection.swift:41:5:44:5 | self | +| testPathInjection.swift:43:9:43:23 | [variable post-update] self | testPathInjection.swift:42:13:42:16 | data | +| testPathInjection.swift:244:9:244:49 | [variable post-update] ascending | testPathInjection.swift:243:5:245:5 | self | +| testPathInjection.swift:244:9:244:49 | [variable post-update] ascending | testPathInjection.swift:243:66:243:74 | ascending | +| testPathInjection.swift:244:9:244:49 | [variable post-update] self | testPathInjection.swift:243:5:245:5 | self | +| testPathInjection.swift:244:9:244:49 | [variable post-update] self | testPathInjection.swift:243:66:243:74 | ascending | +| testPathInjection.swift:349:13:349:58 | [variable post-update] nsData | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:349:13:349:58 | [variable post-update] nsData | testPathInjection.swift:348:9:348:14 | nsData | +| testPathInjection.swift:349:13:349:58 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:349:13:349:58 | [variable post-update] remoteUrl | testPathInjection.swift:348:9:348:14 | nsData | +| testPathInjection.swift:350:5:350:44 | [variable post-update] nsData | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:350:5:350:44 | [variable post-update] nsData | testPathInjection.swift:348:9:348:14 | nsData | +| testPathInjection.swift:350:5:350:44 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:350:5:350:44 | [variable post-update] remoteUrl | testPathInjection.swift:348:9:348:14 | nsData | +| testPathInjection.swift:351:13:351:65 | [variable post-update] nsData | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:351:13:351:65 | [variable post-update] nsData | testPathInjection.swift:348:9:348:14 | nsData | +| testPathInjection.swift:351:13:351:65 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:351:13:351:65 | [variable post-update] remoteString | testPathInjection.swift:348:9:348:14 | nsData | +| testPathInjection.swift:352:5:352:51 | [variable post-update] nsData | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:352:5:352:51 | [variable post-update] nsData | testPathInjection.swift:348:9:348:14 | nsData | +| testPathInjection.swift:352:5:352:51 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:352:5:352:51 | [variable post-update] remoteString | testPathInjection.swift:348:9:348:14 | nsData | +| testPathInjection.swift:355:13:355:94 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:355:13:355:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:355:13:355:94 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:355:13:355:94 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:356:13:356:56 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:356:13:356:56 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:356:13:356:56 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:356:13:356:56 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:357:13:358:86 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:357:13:358:86 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:357:13:358:86 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:357:13:358:86 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:359:13:359:47 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:359:13:359:47 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:359:13:359:47 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:359:13:359:47 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:360:13:360:56 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:360:13:360:56 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:360:13:360:56 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:360:13:360:56 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:361:13:361:45 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:361:13:361:45 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:361:13:361:45 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:361:13:361:45 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:362:5:362:90 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:362:5:362:90 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:362:5:362:90 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:362:5:362:90 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:363:13:363:69 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:363:13:363:69 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:363:13:363:69 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:363:13:363:69 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:364:13:364:79 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:364:13:364:79 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:364:13:364:79 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:364:13:364:79 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:365:5:365:32 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:365:5:365:32 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:365:5:365:32 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:365:5:365:32 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:366:5:366:39 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:366:5:366:39 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:366:5:366:39 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:366:5:366:39 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:367:5:367:94 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:367:5:367:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:367:5:367:94 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:367:5:367:94 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:368:13:368:94 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:368:13:368:94 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:368:13:368:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:368:13:368:94 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:368:13:368:94 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:368:13:368:94 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:368:13:368:94 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:368:13:368:94 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:368:13:368:94 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:369:13:369:94 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:369:13:369:94 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:369:13:369:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:369:13:369:94 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:369:13:369:94 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:369:13:369:94 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:369:13:369:94 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:369:13:369:94 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:369:13:369:94 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:370:5:372:70 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:370:5:372:70 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:370:5:372:70 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:370:5:372:70 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:370:5:372:70 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:370:5:372:70 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:370:5:372:70 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:370:5:372:70 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:370:5:372:70 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:373:5:375:70 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:373:5:375:70 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:373:5:375:70 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:373:5:375:70 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:373:5:375:70 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:373:5:375:70 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:373:5:375:70 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:373:5:375:70 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:373:5:375:70 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:376:5:376:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:376:5:376:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:376:5:376:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:376:5:376:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:376:5:376:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:376:5:376:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:376:5:376:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:376:5:376:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:376:5:376:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:377:5:377:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:377:5:377:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:377:5:377:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:377:5:377:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:377:5:377:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:377:5:377:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:377:5:377:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:377:5:377:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:377:5:377:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:378:5:378:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:378:5:378:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:378:5:378:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:378:5:378:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:379:5:379:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:379:5:379:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:379:5:379:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:379:5:379:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:380:5:380:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:380:5:380:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:380:5:380:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:380:5:380:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:380:5:380:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:380:5:380:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:380:5:380:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:380:5:380:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:380:5:380:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:381:5:381:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:381:5:381:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:381:5:381:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:381:5:381:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:381:5:381:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:381:5:381:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:381:5:381:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:381:5:381:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:381:5:381:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:382:5:382:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:382:5:382:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:382:5:382:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:382:5:382:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:383:5:383:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:383:5:383:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:383:5:383:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:383:5:383:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:384:5:384:69 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:384:5:384:69 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:384:5:384:69 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:384:5:384:69 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:384:5:384:69 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:384:5:384:69 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:384:5:384:69 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:384:5:384:69 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:384:5:384:69 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:385:5:385:69 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:385:5:385:69 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:385:5:385:69 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:385:5:385:69 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:385:5:385:69 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:385:5:385:69 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:385:5:385:69 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:385:5:385:69 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:385:5:385:69 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:386:5:386:72 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:386:5:386:72 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:386:5:386:72 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:386:5:386:72 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:387:5:387:72 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:387:5:387:72 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:387:5:387:72 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:387:5:387:72 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:388:5:388:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:388:5:388:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:388:5:388:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:388:5:388:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:388:5:388:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:388:5:388:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:388:5:388:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:388:5:388:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:388:5:388:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:389:5:389:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:389:5:389:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:389:5:389:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:389:5:389:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:389:5:389:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:389:5:389:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:389:5:389:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:389:5:389:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | +| testPathInjection.swift:389:5:389:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:390:5:390:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:390:5:390:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:390:5:390:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:390:5:390:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:391:5:391:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:391:5:391:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:391:5:391:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:391:5:391:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:392:13:392:62 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:392:13:392:62 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:392:13:392:62 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:392:13:392:62 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:393:13:393:47 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:393:13:393:47 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:393:13:393:47 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:393:13:393:47 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:394:13:395:94 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:394:13:395:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:394:13:395:94 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:394:13:395:94 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:396:5:396:53 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:396:5:396:53 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:396:5:396:53 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:396:5:396:53 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:397:13:397:45 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:397:13:397:45 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:397:13:397:45 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:397:13:397:45 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:398:13:398:63 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:398:13:398:63 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:398:13:398:63 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:398:13:398:63 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:399:13:399:63 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:399:13:399:63 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:399:13:399:63 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:399:13:399:63 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:400:13:400:55 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:400:13:400:55 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:400:13:400:55 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:400:13:400:55 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:401:13:401:85 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:401:13:401:85 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:401:13:401:85 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | +| testPathInjection.swift:401:13:401:85 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:403:13:403:62 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:403:13:403:62 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:403:13:403:62 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:403:13:403:62 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:404:13:404:54 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:404:13:404:54 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:404:13:404:54 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:404:13:404:54 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:405:13:405:69 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:405:13:405:69 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:405:13:405:69 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:405:13:405:69 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:406:13:406:72 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:406:13:406:72 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:406:13:406:72 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:406:13:406:72 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:407:13:407:72 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:407:13:407:72 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:407:13:407:72 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:407:13:407:72 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:408:13:408:62 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:408:13:408:62 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:408:13:408:62 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | +| testPathInjection.swift:408:13:408:62 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:409:13:410:97 | [variable post-update] fm | testPathInjection.swift:342:9:342:19 | remoteNsUrl | +| testPathInjection.swift:409:13:410:97 | [variable post-update] fm | testPathInjection.swift:344:9:344:17 | safeNsUrl | +| testPathInjection.swift:409:13:410:97 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:409:13:410:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:342:9:342:19 | remoteNsUrl | +| testPathInjection.swift:409:13:410:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:344:9:344:17 | safeNsUrl | +| testPathInjection.swift:409:13:410:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:409:13:410:97 | [variable post-update] safeNsUrl | testPathInjection.swift:342:9:342:19 | remoteNsUrl | +| testPathInjection.swift:409:13:410:97 | [variable post-update] safeNsUrl | testPathInjection.swift:344:9:344:17 | safeNsUrl | +| testPathInjection.swift:409:13:410:97 | [variable post-update] safeNsUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:411:13:412:97 | [variable post-update] fm | testPathInjection.swift:342:9:342:19 | remoteNsUrl | +| testPathInjection.swift:411:13:412:97 | [variable post-update] fm | testPathInjection.swift:344:9:344:17 | safeNsUrl | +| testPathInjection.swift:411:13:412:97 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:411:13:412:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:342:9:342:19 | remoteNsUrl | +| testPathInjection.swift:411:13:412:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:344:9:344:17 | safeNsUrl | +| testPathInjection.swift:411:13:412:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:411:13:412:97 | [variable post-update] safeNsUrl | testPathInjection.swift:342:9:342:19 | remoteNsUrl | +| testPathInjection.swift:411:13:412:97 | [variable post-update] safeNsUrl | testPathInjection.swift:344:9:344:17 | safeNsUrl | +| testPathInjection.swift:411:13:412:97 | [variable post-update] safeNsUrl | testPathInjection.swift:354:9:354:10 | fm | +| testPathInjection.swift:478:5:478:60 | [variable post-update] buffer1 | testPathInjection.swift:339:11:339:17 | buffer1 | +| testPathInjection.swift:478:5:478:60 | [variable post-update] buffer1 | testPathInjection.swift:476:9:476:17 | localData | +| testPathInjection.swift:478:5:478:60 | [variable post-update] localData | testPathInjection.swift:339:11:339:17 | buffer1 | +| testPathInjection.swift:478:5:478:60 | [variable post-update] localData | testPathInjection.swift:339:11:339:17 | buffer1 | +| testPathInjection.swift:478:5:478:60 | [variable post-update] localData | testPathInjection.swift:476:9:476:17 | localData | +| testPathInjection.swift:478:5:478:60 | [variable post-update] localData | testPathInjection.swift:476:9:476:17 | localData | +| testPathInjection.swift:479:5:479:62 | [variable post-update] buffer2 | testPathInjection.swift:339:49:339:55 | buffer2 | +| testPathInjection.swift:479:5:479:62 | [variable post-update] buffer2 | testPathInjection.swift:477:9:477:18 | remoteData | +| testPathInjection.swift:479:5:479:62 | [variable post-update] remoteData | testPathInjection.swift:339:49:339:55 | buffer2 | +| testPathInjection.swift:479:5:479:62 | [variable post-update] remoteData | testPathInjection.swift:339:49:339:55 | buffer2 | +| testPathInjection.swift:479:5:479:62 | [variable post-update] remoteData | testPathInjection.swift:477:9:477:18 | remoteData | +| testPathInjection.swift:479:5:479:62 | [variable post-update] remoteData | testPathInjection.swift:477:9:477:18 | remoteData | +| testPathInjection.swift:510:17:510:49 | [variable post-update] fm | testPathInjection.swift:504:9:504:20 | remoteString | +| testPathInjection.swift:510:17:510:49 | [variable post-update] fm | testPathInjection.swift:506:9:506:10 | fm | +| testPathInjection.swift:510:17:510:49 | [variable post-update] remoteString | testPathInjection.swift:504:9:504:20 | remoteString | +| testPathInjection.swift:510:17:510:49 | [variable post-update] remoteString | testPathInjection.swift:506:9:506:10 | fm | +| testPathInjection.swift:512:13:512:45 | [variable post-update] fm | testPathInjection.swift:504:9:504:20 | remoteString | +| testPathInjection.swift:512:13:512:45 | [variable post-update] fm | testPathInjection.swift:506:9:506:10 | fm | +| testPathInjection.swift:512:13:512:45 | [variable post-update] remoteString | testPathInjection.swift:504:9:504:20 | remoteString | +| testPathInjection.swift:512:13:512:45 | [variable post-update] remoteString | testPathInjection.swift:506:9:506:10 | fm | +| testPathInjection.swift:524:28:524:66 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:524:28:524:66 | [variable post-update] remoteString | testPathInjection.swift:521:9:521:10 | u1 | +| testPathInjection.swift:524:28:524:66 | [variable post-update] u1 | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:524:28:524:66 | [variable post-update] u1 | testPathInjection.swift:521:9:521:10 | u1 | +| testPathInjection.swift:525:28:525:66 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:525:28:525:66 | [variable post-update] remoteString | testPathInjection.swift:521:9:521:10 | u1 | +| testPathInjection.swift:525:28:525:66 | [variable post-update] u1 | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:525:28:525:66 | [variable post-update] u1 | testPathInjection.swift:521:9:521:10 | u1 | +| testPathInjection.swift:526:5:526:40 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:526:5:526:40 | [variable post-update] remoteString | testPathInjection.swift:521:9:521:10 | u1 | +| testPathInjection.swift:526:5:526:40 | [variable post-update] u1 | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:526:5:526:40 | [variable post-update] u1 | testPathInjection.swift:521:9:521:10 | u1 | +| testPathInjection.swift:535:24:535:62 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:535:24:535:62 | [variable post-update] remoteString | testPathInjection.swift:532:9:532:10 | u3 | +| testPathInjection.swift:535:24:535:62 | [variable post-update] u3 | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:535:24:535:62 | [variable post-update] u3 | testPathInjection.swift:532:9:532:10 | u3 | +| testPathInjection.swift:554:9:555:75 | [variable post-update] remoteString | testPathInjection.swift:517:5:517:6 | s3 | +| testPathInjection.swift:554:9:555:75 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:554:9:555:75 | [variable post-update] s3 | testPathInjection.swift:517:5:517:6 | s3 | +| testPathInjection.swift:554:9:555:75 | [variable post-update] s3 | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:559:9:559:67 | [variable post-update] fm | testPathInjection.swift:517:39:517:40 | fm | +| testPathInjection.swift:559:9:559:67 | [variable post-update] fm | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:559:9:559:67 | [variable post-update] remoteString | testPathInjection.swift:517:39:517:40 | fm | +| testPathInjection.swift:559:9:559:67 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:560:13:560:53 | [variable post-update] fm | testPathInjection.swift:517:39:517:40 | fm | +| testPathInjection.swift:560:13:560:53 | [variable post-update] fm | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:560:13:560:53 | [variable post-update] remoteString | testPathInjection.swift:517:39:517:40 | fm | +| testPathInjection.swift:560:13:560:53 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | +| testPathInjection.swift:587:5:587:41 | [variable post-update] mc | testPathInjection.swift:580:9:580:20 | remoteString | +| testPathInjection.swift:587:5:587:41 | [variable post-update] mc | testPathInjection.swift:586:9:586:10 | mc | +| testPathInjection.swift:587:5:587:41 | [variable post-update] remoteString | testPathInjection.swift:580:9:580:20 | remoteString | +| testPathInjection.swift:587:5:587:41 | [variable post-update] remoteString | testPathInjection.swift:586:9:586:10 | mc | +| testPathInjection.swift:588:5:588:34 | [variable post-update] mc | testPathInjection.swift:580:9:580:20 | remoteString | +| testPathInjection.swift:588:5:588:34 | [variable post-update] mc | testPathInjection.swift:586:9:586:10 | mc | +| testPathInjection.swift:588:5:588:34 | [variable post-update] remoteString | testPathInjection.swift:580:9:580:20 | remoteString | +| testPathInjection.swift:588:5:588:34 | [variable post-update] remoteString | testPathInjection.swift:586:9:586:10 | mc | From b1b2b2008c61872085b2bf1a7e760e557cb94adc Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 13:08:04 +0200 Subject: [PATCH 04/40] ssa: Expose new consistency check from VariableCapture.qll --- csharp/ql/consistency-queries/SsaConsistency.ql | 1 + java/ql/consistency-queries/SsaConsistency.ql | 1 + ruby/ql/consistency-queries/SsaConsistency.ql | 1 + rust/ql/consistency-queries/SsaConsistency.ql | 1 + shared/dataflow/codeql/dataflow/VariableCapture.qll | 2 ++ 5 files changed, 6 insertions(+) diff --git a/csharp/ql/consistency-queries/SsaConsistency.ql b/csharp/ql/consistency-queries/SsaConsistency.ql index 6b3f4510e487..152258220a7f 100644 --- a/csharp/ql/consistency-queries/SsaConsistency.ql +++ b/csharp/ql/consistency-queries/SsaConsistency.ql @@ -1,6 +1,7 @@ import csharp import semmle.code.csharp.dataflow.internal.SsaImpl as Impl import Impl::Consistency +import Impl::DataFlowIntegration::DfConsistency import Ssa query predicate localDeclWithSsaDef(LocalVariableDeclExpr d) { diff --git a/java/ql/consistency-queries/SsaConsistency.ql b/java/ql/consistency-queries/SsaConsistency.ql index b62db63ac5ba..2ea5604d5b7e 100644 --- a/java/ql/consistency-queries/SsaConsistency.ql +++ b/java/ql/consistency-queries/SsaConsistency.ql @@ -1,3 +1,4 @@ import java import semmle.code.java.dataflow.internal.SsaImpl import Impl::Consistency +import DataFlowIntegration::DfConsistency diff --git a/ruby/ql/consistency-queries/SsaConsistency.ql b/ruby/ql/consistency-queries/SsaConsistency.ql index 235eac263442..a0f1cb23cfef 100644 --- a/ruby/ql/consistency-queries/SsaConsistency.ql +++ b/ruby/ql/consistency-queries/SsaConsistency.ql @@ -1,3 +1,4 @@ import codeql.ruby.dataflow.SSA import codeql.ruby.dataflow.internal.SsaImpl import Consistency +import DataFlowIntegration::DfConsistency diff --git a/rust/ql/consistency-queries/SsaConsistency.ql b/rust/ql/consistency-queries/SsaConsistency.ql index 1774f269749c..4cbce78c5207 100644 --- a/rust/ql/consistency-queries/SsaConsistency.ql +++ b/rust/ql/consistency-queries/SsaConsistency.ql @@ -8,3 +8,4 @@ import codeql.rust.dataflow.Ssa import codeql.rust.dataflow.internal.SsaImpl import Consistency +import DataFlowIntegration::DfConsistency diff --git a/shared/dataflow/codeql/dataflow/VariableCapture.qll b/shared/dataflow/codeql/dataflow/VariableCapture.qll index 0ba44be5ea1f..ab798b02cf2d 100644 --- a/shared/dataflow/codeql/dataflow/VariableCapture.qll +++ b/shared/dataflow/codeql/dataflow/VariableCapture.qll @@ -389,6 +389,8 @@ module Flow< msg = "Callable has multiple locations" and 2 <= strictcount(c.getLocation()) } + import SsaFlow::DfConsistency + query predicate consistencyOverview(string msg, int n) { uniqueToString(msg, n) or n = strictcount(BasicBlock bb | uniqueEnclosingCallable(bb, msg)) or From b2f9e09f2cd9e320bbf43454aea4883ad8ea2567 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 15:35:03 +0200 Subject: [PATCH 05/40] ssa: Record ambiguousReadNode errors from VariableCapture These consistency violations originate from the VariableCapture instantation in C#, JS, Python, and Ruby. --- .../VariableCaptureConsistency.expected | 39 +++++++++ .../VariableCaptureConsistency.expected | 17 ++++ .../VariableCaptureConsistency.expected | 23 +++++ .../VariableCaptureConsistency.expected | 5 ++ .../VariableCaptureConsistency.expected | 3 + .../VariableCaptureConsistency.expected | 9 ++ .../FlowSummary/CaptureConsistency.expected | 1 + .../dataflow-capture-consistency.expected | 29 +++++++ .../CONSISTENCY/VariablesConsistency.expected | 27 ++++++ .../CONSISTENCY/VariablesConsistency.expected | 11 +++ .../CONSISTENCY/VariablesConsistency.expected | 15 ++++ .../CONSISTENCY/VariablesConsistency.expected | 3 + .../CONSISTENCY/VariablesConsistency.expected | 5 ++ .../CONSISTENCY/VariablesConsistency.expected | 3 + .../CONSISTENCY/VariablesConsistency.expected | 3 + .../CONSISTENCY/VariablesConsistency.expected | 85 +++++++++++++++++++ .../CONSISTENCY/VariablesConsistency.expected | 3 + .../CONSISTENCY/VariablesConsistency.expected | 3 + .../CONSISTENCY/VariablesConsistency.expected | 6 ++ .../CONSISTENCY/VariablesConsistency.expected | 3 + .../CONSISTENCY/VariablesConsistency.expected | 3 + .../CONSISTENCY/VariablesConsistency.expected | 15 ++++ .../CONSISTENCY/VariablesConsistency.expected | 3 + .../CONSISTENCY/VariablesConsistency.expected | 5 ++ .../CONSISTENCY/VariablesConsistency.expected | 5 ++ .../CONSISTENCY/VariablesConsistency.expected | 5 ++ .../CONSISTENCY/VariablesConsistency.expected | 3 + .../VariableCaptureConsistency.expected | 3 + .../VariableCaptureConsistency.expected | 17 ++++ 29 files changed, 352 insertions(+) create mode 100644 csharp/ql/test/library-tests/dataflow/global/CONSISTENCY/VariableCaptureConsistency.expected create mode 100644 csharp/ql/test/library-tests/dataflow/local/CONSISTENCY/VariableCaptureConsistency.expected create mode 100644 csharp/ql/test/library-tests/dataflow/ssa/CONSISTENCY/VariableCaptureConsistency.expected create mode 100644 csharp/ql/test/query-tests/Likely Bugs/ThreadUnsafeICryptoTransformLambda/CONSISTENCY/VariableCaptureConsistency.expected create mode 100644 csharp/ql/test/query-tests/Nullness/CONSISTENCY/VariableCaptureConsistency.expected create mode 100644 csharp/ql/test/query-tests/standalone/Language Abuse/SimplifyBoolExpr/CONSISTENCY/VariableCaptureConsistency.expected create mode 100644 ruby/ql/test/library-tests/ast/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/ast/calls/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/ast/control/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/ast/erb/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/controlflow/graph/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/dataflow/array-flow/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/dataflow/call-sensitivity/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/dataflow/global/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/dataflow/local/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/frameworks/action_view/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/frameworks/rack/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/frameworks/sinatra/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/modules/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/library-tests/variables/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/query-tests/experimental/InsecureRandomness/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/query-tests/experimental/improper-memoization/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/query-tests/security/cwe-079/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/query-tests/variables/DeadStoreOfLocal/CONSISTENCY/VariablesConsistency.expected create mode 100644 ruby/ql/test/query-tests/variables/UninitializedLocal/CONSISTENCY/VariablesConsistency.expected create mode 100644 rust/ql/test/library-tests/controlflow/CONSISTENCY/VariableCaptureConsistency.expected create mode 100644 rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/VariableCaptureConsistency.expected diff --git a/csharp/ql/test/library-tests/dataflow/global/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/library-tests/dataflow/global/CONSISTENCY/VariableCaptureConsistency.expected new file mode 100644 index 000000000000..938ee32c47d1 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/global/CONSISTENCY/VariableCaptureConsistency.expected @@ -0,0 +1,39 @@ +ambiguousReadNode +| Capture.cs:16:9:24:9 | CaptureIn2(...) | Capture.cs:7:10:7:11 | this in In | +| Capture.cs:16:9:24:9 | CaptureIn2(...) | Capture.cs:7:20:7:26 | tainted | +| Capture.cs:25:9:25:18 | access to local function CaptureIn2 | Capture.cs:7:10:7:11 | this in In | +| Capture.cs:25:9:25:18 | access to local function CaptureIn2 | Capture.cs:7:20:7:26 | tainted | +| Capture.cs:52:23:59:13 | (...) => ... | Capture.cs:50:33:50:40 | nonSink0 | +| Capture.cs:52:23:59:13 | (...) => ... | Capture.cs:50:50:50:55 | sink39 | +| Capture.cs:75:9:82:9 | CaptureOut2(...) | Capture.cs:64:10:64:12 | this in Out | +| Capture.cs:75:9:82:9 | CaptureOut2(...) | Capture.cs:74:16:74:21 | sink31 | +| Capture.cs:83:9:83:19 | access to local function CaptureOut2 | Capture.cs:64:10:64:12 | this in Out | +| Capture.cs:83:9:83:19 | access to local function CaptureOut2 | Capture.cs:74:16:74:21 | sink31 | +| Capture.cs:112:9:122:9 | CaptureOutMultipleLambdas(...) | Capture.cs:95:16:95:23 | nonSink0 | +| Capture.cs:112:9:122:9 | CaptureOutMultipleLambdas(...) | Capture.cs:111:16:111:21 | sink40 | +| Capture.cs:123:9:123:33 | access to local function CaptureOutMultipleLambdas | Capture.cs:95:16:95:23 | nonSink0 | +| Capture.cs:123:9:123:33 | access to local function CaptureOutMultipleLambdas | Capture.cs:111:16:111:21 | sink40 | +| Capture.cs:130:9:133:9 | CaptureThrough1(...) | Capture.cs:127:25:127:31 | tainted | +| Capture.cs:130:9:133:9 | CaptureThrough1(...) | Capture.cs:129:16:129:21 | sink33 | +| Capture.cs:134:9:134:23 | access to local function CaptureThrough1 | Capture.cs:127:25:127:31 | tainted | +| Capture.cs:134:9:134:23 | access to local function CaptureThrough1 | Capture.cs:129:16:129:21 | sink33 | +| Capture.cs:138:9:145:9 | CaptureThrough2(...) | Capture.cs:127:10:127:16 | this in Through | +| Capture.cs:138:9:145:9 | CaptureThrough2(...) | Capture.cs:127:25:127:31 | tainted | +| Capture.cs:138:9:145:9 | CaptureThrough2(...) | Capture.cs:137:16:137:21 | sink34 | +| Capture.cs:146:9:146:23 | access to local function CaptureThrough2 | Capture.cs:127:10:127:16 | this in Through | +| Capture.cs:146:9:146:23 | access to local function CaptureThrough2 | Capture.cs:127:25:127:31 | tainted | +| Capture.cs:146:9:146:23 | access to local function CaptureThrough2 | Capture.cs:137:16:137:21 | sink34 | +| Capture.cs:150:48:154:9 | (...) => ... | Capture.cs:127:25:127:31 | tainted | +| Capture.cs:150:48:154:9 | (...) => ... | Capture.cs:149:16:149:21 | sink35 | +| Capture.cs:155:30:155:44 | access to local variable captureThrough3 | Capture.cs:127:25:127:31 | tainted | +| Capture.cs:155:30:155:44 | access to local variable captureThrough3 | Capture.cs:149:16:149:21 | sink35 | +| Capture.cs:174:9:177:9 | CaptureThrough1NotCalled(...) | Capture.cs:127:25:127:31 | tainted | +| Capture.cs:174:9:177:9 | CaptureThrough1NotCalled(...) | Capture.cs:173:16:173:23 | nonSink0 | +| Capture.cs:180:9:186:9 | CaptureThrough2NotCalled(...) | Capture.cs:127:25:127:31 | tainted | +| Capture.cs:180:9:186:9 | CaptureThrough2NotCalled(...) | Capture.cs:173:16:173:23 | nonSink0 | +| Capture.cs:187:9:187:32 | access to local function CaptureThrough2NotCalled | Capture.cs:127:25:127:31 | tainted | +| Capture.cs:187:9:187:32 | access to local function CaptureThrough2NotCalled | Capture.cs:173:16:173:23 | nonSink0 | +| Capture.cs:332:9:332:65 | CapturingLocalFunction(...) | Capture.cs:326:10:326:12 | this in M12 | +| Capture.cs:332:9:332:65 | CapturingLocalFunction(...) | Capture.cs:328:13:328:13 | x | +| Capture.cs:334:9:334:30 | access to local function CapturingLocalFunction | Capture.cs:326:10:326:12 | this in M12 | +| Capture.cs:334:9:334:30 | access to local function CapturingLocalFunction | Capture.cs:328:13:328:13 | x | diff --git a/csharp/ql/test/library-tests/dataflow/local/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/library-tests/dataflow/local/CONSISTENCY/VariableCaptureConsistency.expected new file mode 100644 index 000000000000..b790fa24b23f --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/local/CONSISTENCY/VariableCaptureConsistency.expected @@ -0,0 +1,17 @@ +ambiguousReadNode +| Capture.cs:15:9:22:9 | CapIn2(...) | Capture.cs:5:17:5:17 | this in M | +| Capture.cs:15:9:22:9 | CapIn2(...) | Capture.cs:7:13:7:13 | i | +| Capture.cs:23:9:23:14 | access to local function CapIn2 | Capture.cs:5:17:5:17 | this in M | +| Capture.cs:23:9:23:14 | access to local function CapIn2 | Capture.cs:7:13:7:13 | i | +| Capture.cs:25:9:33:9 | CapIn4(...) | Capture.cs:5:17:5:17 | this in M | +| Capture.cs:25:9:33:9 | CapIn4(...) | Capture.cs:7:13:7:13 | i | +| Capture.cs:34:9:34:14 | access to local function CapIn4 | Capture.cs:5:17:5:17 | this in M | +| Capture.cs:34:9:34:14 | access to local function CapIn4 | Capture.cs:7:13:7:13 | i | +| Capture.cs:43:9:50:9 | CapOut2(...) | Capture.cs:5:17:5:17 | this in M | +| Capture.cs:43:9:50:9 | CapOut2(...) | Capture.cs:7:13:7:13 | i | +| Capture.cs:51:9:51:15 | access to local function CapOut2 | Capture.cs:5:17:5:17 | this in M | +| Capture.cs:51:9:51:15 | access to local function CapOut2 | Capture.cs:7:13:7:13 | i | +| Capture.cs:54:9:62:9 | CapOut4(...) | Capture.cs:5:17:5:17 | this in M | +| Capture.cs:54:9:62:9 | CapOut4(...) | Capture.cs:7:13:7:13 | i | +| Capture.cs:63:9:63:15 | access to local function CapOut4 | Capture.cs:5:17:5:17 | this in M | +| Capture.cs:63:9:63:15 | access to local function CapOut4 | Capture.cs:7:13:7:13 | i | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/library-tests/dataflow/ssa/CONSISTENCY/VariableCaptureConsistency.expected new file mode 100644 index 000000000000..f3c4bb63106d --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/ssa/CONSISTENCY/VariableCaptureConsistency.expected @@ -0,0 +1,23 @@ +ambiguousReadNode +| Capture.cs:10:20:27:9 | (...) => ... | Capture.cs:6:16:6:16 | i | +| Capture.cs:10:20:27:9 | (...) => ... | Capture.cs:8:13:8:13 | x | +| Capture.cs:19:24:23:13 | (...) => ... | Capture.cs:10:20:27:9 | this | +| Capture.cs:19:24:23:13 | (...) => ... | Capture.cs:17:17:17:17 | y | +| Capture.cs:25:13:25:13 | access to local variable b | Capture.cs:10:20:27:9 | this | +| Capture.cs:25:13:25:13 | access to local variable b | Capture.cs:17:17:17:17 | y | +| Capture.cs:38:9:38:9 | access to local variable a | Capture.cs:6:16:6:16 | i | +| Capture.cs:38:9:38:9 | access to local variable a | Capture.cs:8:13:8:13 | x | +| Capture.cs:46:12:46:12 | access to local variable a | Capture.cs:6:16:6:16 | i | +| Capture.cs:46:12:46:12 | access to local variable a | Capture.cs:8:13:8:13 | x | +| Capture.cs:169:9:178:9 | M8(...) | Capture.cs:112:10:112:28 | this in NestedFunctionsTest | +| Capture.cs:169:9:178:9 | M8(...) | Capture.cs:168:13:168:13 | h | +| Capture.cs:248:9:252:9 | CaptureAndRef(...) | Capture.cs:240:10:240:11 | this in M2 | +| Capture.cs:248:9:252:9 | CaptureAndRef(...) | Capture.cs:242:13:242:13 | i | +| Capture.cs:254:9:254:21 | access to local function CaptureAndRef | Capture.cs:240:10:240:11 | this in M2 | +| Capture.cs:254:9:254:21 | access to local function CaptureAndRef | Capture.cs:242:13:242:13 | i | +| Consistency.cs:39:20:39:43 | (...) => ... | Consistency.cs:36:10:36:27 | this in CapturedDeclNoInit | +| Consistency.cs:39:20:39:43 | (...) => ... | Consistency.cs:38:13:38:13 | i | +| Fields.cs:81:9:81:9 | access to local variable a | Fields.cs:77:13:77:13 | f | +| Fields.cs:81:9:81:9 | access to local variable a | Fields.cs:78:23:78:23 | a | +| Properties.cs:77:9:77:9 | access to local variable a | Properties.cs:73:13:73:13 | f | +| Properties.cs:77:9:77:9 | access to local variable a | Properties.cs:74:23:74:23 | a | diff --git a/csharp/ql/test/query-tests/Likely Bugs/ThreadUnsafeICryptoTransformLambda/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/query-tests/Likely Bugs/ThreadUnsafeICryptoTransformLambda/CONSISTENCY/VariableCaptureConsistency.expected new file mode 100644 index 000000000000..becc963c0fe5 --- /dev/null +++ b/csharp/ql/test/query-tests/Likely Bugs/ThreadUnsafeICryptoTransformLambda/CONSISTENCY/VariableCaptureConsistency.expected @@ -0,0 +1,5 @@ +ambiguousReadNode +| ThreadUnsafeICryptoTransformLambda.cs:16:24:22:9 | (...) => ... | ThreadUnsafeICryptoTransformLambda.cs:10:32:10:34 | max | +| ThreadUnsafeICryptoTransformLambda.cs:16:24:22:9 | (...) => ... | ThreadUnsafeICryptoTransformLambda.cs:15:13:15:16 | sha1 | +| ThreadUnsafeICryptoTransformLambda.cs:80:24:86:9 | (...) => ... | ThreadUnsafeICryptoTransformLambda.cs:73:32:73:34 | max | +| ThreadUnsafeICryptoTransformLambda.cs:80:24:86:9 | (...) => ... | ThreadUnsafeICryptoTransformLambda.cs:77:13:77:16 | sha1 | diff --git a/csharp/ql/test/query-tests/Nullness/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/query-tests/Nullness/CONSISTENCY/VariableCaptureConsistency.expected new file mode 100644 index 000000000000..4bbdd3f461de --- /dev/null +++ b/csharp/ql/test/query-tests/Nullness/CONSISTENCY/VariableCaptureConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| A.cs:61:31:61:45 | (...) => ... | A.cs:61:26:61:26 | e | +| A.cs:61:31:61:45 | (...) => ... | A.cs:61:26:61:45 | this | diff --git a/csharp/ql/test/query-tests/standalone/Language Abuse/SimplifyBoolExpr/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/query-tests/standalone/Language Abuse/SimplifyBoolExpr/CONSISTENCY/VariableCaptureConsistency.expected new file mode 100644 index 000000000000..bc7a35a116b4 --- /dev/null +++ b/csharp/ql/test/query-tests/standalone/Language Abuse/SimplifyBoolExpr/CONSISTENCY/VariableCaptureConsistency.expected @@ -0,0 +1,9 @@ +ambiguousReadNode +| SimplifyBoolExpr.cs:53:29:53:50 | (...) => ... | SimplifyBoolExpr.cs:50:65:50:68 | left | +| SimplifyBoolExpr.cs:53:29:53:50 | (...) => ... | SimplifyBoolExpr.cs:50:100:50:104 | right | +| SimplifyBoolExpr.cs:56:9:56:41 | Local(...) | SimplifyBoolExpr.cs:50:65:50:68 | left | +| SimplifyBoolExpr.cs:56:9:56:41 | Local(...) | SimplifyBoolExpr.cs:50:100:50:104 | right | +| SimplifyBoolExpr.cs:58:16:58:21 | access to local variable lambda | SimplifyBoolExpr.cs:50:65:50:68 | left | +| SimplifyBoolExpr.cs:58:16:58:21 | access to local variable lambda | SimplifyBoolExpr.cs:50:100:50:104 | right | +| SimplifyBoolExpr.cs:58:28:58:32 | access to local function Local | SimplifyBoolExpr.cs:50:65:50:68 | left | +| SimplifyBoolExpr.cs:58:28:58:32 | access to local function Local | SimplifyBoolExpr.cs:50:100:50:104 | right | diff --git a/javascript/ql/test/library-tests/FlowSummary/CaptureConsistency.expected b/javascript/ql/test/library-tests/FlowSummary/CaptureConsistency.expected index 35f4edcf1fb9..e331f0ddde45 100644 --- a/javascript/ql/test/library-tests/FlowSummary/CaptureConsistency.expected +++ b/javascript/ql/test/library-tests/FlowSummary/CaptureConsistency.expected @@ -15,3 +15,4 @@ closureAliasMustBeInSameScope variableAccessAstNesting uniqueCallableLocation consistencyOverview +ambiguousReadNode diff --git a/python/ql/test/library-tests/dataflow/variable-capture/dataflow-capture-consistency.expected b/python/ql/test/library-tests/dataflow/variable-capture/dataflow-capture-consistency.expected index 35f4edcf1fb9..2837533cd483 100644 --- a/python/ql/test/library-tests/dataflow/variable-capture/dataflow-capture-consistency.expected +++ b/python/ql/test/library-tests/dataflow/variable-capture/dataflow-capture-consistency.expected @@ -15,3 +15,32 @@ closureAliasMustBeInSameScope variableAccessAstNesting uniqueCallableLocation consistencyOverview +ambiguousReadNode +| dict.py:67:5:67:22 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable sinkO1 | +| dict.py:67:5:67:22 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable tainted | +| dict.py:69:5:69:15 | ControlFlowNode for captureOut1 | dict.py:65:1:65:21 | Local Variable sinkO1 | +| dict.py:69:5:69:15 | ControlFlowNode for captureOut1 | dict.py:65:1:65:21 | Local Variable tainted | +| dict.py:73:5:73:22 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable sinkO2 | +| dict.py:73:5:73:22 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable tainted | +| dict.py:77:5:77:15 | ControlFlowNode for captureOut2 | dict.py:65:1:65:21 | Local Variable sinkO2 | +| dict.py:77:5:77:15 | ControlFlowNode for captureOut2 | dict.py:65:1:65:21 | Local Variable tainted | +| dict.py:81:5:81:31 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable nonSink1 | +| dict.py:81:5:81:31 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable tainted | +| dict.py:86:5:86:31 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable nonSink2 | +| dict.py:86:5:86:31 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable tainted | +| dict.py:90:5:90:24 | ControlFlowNode for captureOut2NotCalled | dict.py:65:1:65:21 | Local Variable nonSink2 | +| dict.py:90:5:90:24 | ControlFlowNode for captureOut2NotCalled | dict.py:65:1:65:21 | Local Variable tainted | +| nonlocal.py:73:5:73:22 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable sinkO1 | +| nonlocal.py:73:5:73:22 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable tainted | +| nonlocal.py:76:5:76:15 | ControlFlowNode for captureOut1 | nonlocal.py:71:1:71:21 | Local Variable sinkO1 | +| nonlocal.py:76:5:76:15 | ControlFlowNode for captureOut1 | nonlocal.py:71:1:71:21 | Local Variable tainted | +| nonlocal.py:80:5:80:22 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable sinkO2 | +| nonlocal.py:80:5:80:22 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable tainted | +| nonlocal.py:85:5:85:15 | ControlFlowNode for captureOut2 | nonlocal.py:71:1:71:21 | Local Variable sinkO2 | +| nonlocal.py:85:5:85:15 | ControlFlowNode for captureOut2 | nonlocal.py:71:1:71:21 | Local Variable tainted | +| nonlocal.py:89:5:89:31 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable nonSink1 | +| nonlocal.py:89:5:89:31 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable tainted | +| nonlocal.py:95:5:95:31 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable nonSink2 | +| nonlocal.py:95:5:95:31 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable tainted | +| nonlocal.py:100:5:100:24 | ControlFlowNode for captureOut2NotCalled | nonlocal.py:71:1:71:21 | Local Variable nonSink2 | +| nonlocal.py:100:5:100:24 | ControlFlowNode for captureOut2NotCalled | nonlocal.py:71:1:71:21 | Local Variable tainted | diff --git a/ruby/ql/test/library-tests/ast/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/ast/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..9b218f507380 --- /dev/null +++ b/ruby/ql/test/library-tests/ast/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,27 @@ +ambiguousReadNode +| calls/calls.rb:223:1:225:3 | { ... } | calls/calls.rb:1:1:367:24 | self | +| calls/calls.rb:223:1:225:3 | { ... } | calls/calls.rb:223:5:223:5 | x | +| calls/calls.rb:343:1:345:3 | { ... } | calls/calls.rb:1:1:367:24 | self | +| calls/calls.rb:343:1:345:3 | { ... } | calls/calls.rb:223:5:223:5 | x | +| calls/calls.rb:343:1:345:3 | { ... } | calls/calls.rb:343:8:343:8 | y | +| calls/calls.rb:343:1:345:3 | { ... } | calls/calls.rb:343:11:343:11 | z | +| calls/calls.rb:357:1:361:3 | ... = ... | calls/calls.rb:1:1:367:24 | self | +| calls/calls.rb:357:1:361:3 | ... = ... | calls/calls.rb:343:8:343:8 | y | +| calls/calls.rb:357:5:361:3 | -> { ... } | calls/calls.rb:1:1:367:24 | self | +| calls/calls.rb:357:5:361:3 | -> { ... } | calls/calls.rb:343:8:343:8 | y | +| control/loops.rb:9:1:12:3 | { ... } | control/loops.rb:2:1:2:3 | foo | +| control/loops.rb:9:1:12:3 | { ... } | control/loops.rb:3:1:3:3 | sum | +| control/loops.rb:9:1:12:3 | { ... } | control/loops.rb:9:5:9:5 | n | +| control/loops.rb:16:1:19:3 | { ... } | control/loops.rb:2:1:2:3 | foo | +| control/loops.rb:16:1:19:3 | { ... } | control/loops.rb:3:1:3:3 | sum | +| control/loops.rb:16:1:19:3 | { ... } | control/loops.rb:9:5:9:5 | n | +| control/loops.rb:22:1:25:3 | { ... } | control/loops.rb:2:1:2:3 | foo | +| control/loops.rb:22:1:25:3 | { ... } | control/loops.rb:3:1:3:3 | sum | +| control/loops.rb:22:1:25:3 | { ... } | control/loops.rb:22:5:22:7 | key | +| control/loops.rb:22:1:25:3 | { ... } | control/loops.rb:22:10:22:14 | value | +| control/loops.rb:28:1:32:3 | { ... } | control/loops.rb:2:1:2:3 | foo | +| control/loops.rb:28:1:32:3 | { ... } | control/loops.rb:3:1:3:3 | sum | +| control/loops.rb:28:1:32:3 | { ... } | control/loops.rb:22:5:22:7 | key | +| control/loops.rb:28:1:32:3 | { ... } | control/loops.rb:22:10:22:14 | value | +| erb/template.html.erb:27:6:31:8 | { ... } | erb/template.html.erb:25:4:25:5 | xs | +| erb/template.html.erb:27:6:31:8 | { ... } | erb/template.html.erb:27:10:27:10 | x | diff --git a/ruby/ql/test/library-tests/ast/calls/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/ast/calls/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..7440cff458c8 --- /dev/null +++ b/ruby/ql/test/library-tests/ast/calls/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,11 @@ +ambiguousReadNode +| calls.rb:223:1:225:3 | { ... } | calls.rb:1:1:367:24 | self | +| calls.rb:223:1:225:3 | { ... } | calls.rb:223:5:223:5 | x | +| calls.rb:343:1:345:3 | { ... } | calls.rb:1:1:367:24 | self | +| calls.rb:343:1:345:3 | { ... } | calls.rb:223:5:223:5 | x | +| calls.rb:343:1:345:3 | { ... } | calls.rb:343:8:343:8 | y | +| calls.rb:343:1:345:3 | { ... } | calls.rb:343:11:343:11 | z | +| calls.rb:357:1:361:3 | ... = ... | calls.rb:1:1:367:24 | self | +| calls.rb:357:1:361:3 | ... = ... | calls.rb:343:8:343:8 | y | +| calls.rb:357:5:361:3 | -> { ... } | calls.rb:1:1:367:24 | self | +| calls.rb:357:5:361:3 | -> { ... } | calls.rb:343:8:343:8 | y | diff --git a/ruby/ql/test/library-tests/ast/control/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/ast/control/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..366b4928e753 --- /dev/null +++ b/ruby/ql/test/library-tests/ast/control/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,15 @@ +ambiguousReadNode +| loops.rb:9:1:12:3 | { ... } | loops.rb:2:1:2:3 | foo | +| loops.rb:9:1:12:3 | { ... } | loops.rb:3:1:3:3 | sum | +| loops.rb:9:1:12:3 | { ... } | loops.rb:9:5:9:5 | n | +| loops.rb:16:1:19:3 | { ... } | loops.rb:2:1:2:3 | foo | +| loops.rb:16:1:19:3 | { ... } | loops.rb:3:1:3:3 | sum | +| loops.rb:16:1:19:3 | { ... } | loops.rb:9:5:9:5 | n | +| loops.rb:22:1:25:3 | { ... } | loops.rb:2:1:2:3 | foo | +| loops.rb:22:1:25:3 | { ... } | loops.rb:3:1:3:3 | sum | +| loops.rb:22:1:25:3 | { ... } | loops.rb:22:5:22:7 | key | +| loops.rb:22:1:25:3 | { ... } | loops.rb:22:10:22:14 | value | +| loops.rb:28:1:32:3 | { ... } | loops.rb:2:1:2:3 | foo | +| loops.rb:28:1:32:3 | { ... } | loops.rb:3:1:3:3 | sum | +| loops.rb:28:1:32:3 | { ... } | loops.rb:22:5:22:7 | key | +| loops.rb:28:1:32:3 | { ... } | loops.rb:22:10:22:14 | value | diff --git a/ruby/ql/test/library-tests/ast/erb/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/ast/erb/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..636387e9a992 --- /dev/null +++ b/ruby/ql/test/library-tests/ast/erb/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| template.html.erb:27:6:31:8 | { ... } | template.html.erb:25:4:25:5 | xs | +| template.html.erb:27:6:31:8 | { ... } | template.html.erb:27:10:27:10 | x | diff --git a/ruby/ql/test/library-tests/controlflow/graph/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/controlflow/graph/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..1fe0734c92df --- /dev/null +++ b/ruby/ql/test/library-tests/controlflow/graph/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,5 @@ +ambiguousReadNode +| cfg.rb:90:1:93:3 | { ... } | cfg.rb:1:1:221:1 | self | +| cfg.rb:90:1:93:3 | { ... } | cfg.rb:74:1:74:1 | x | +| raise.rb:155:16:155:50 | { ... } | raise.rb:154:1:156:3 | self | +| raise.rb:155:16:155:50 | { ... } | raise.rb:154:9:154:15 | element | diff --git a/ruby/ql/test/library-tests/dataflow/array-flow/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/dataflow/array-flow/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..2af36de73337 --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/array-flow/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| array_flow.rb:404:9:406:7 | { ... } | array_flow.rb:402:1:409:3 | self | +| array_flow.rb:404:9:406:7 | { ... } | array_flow.rb:404:13:404:13 | x | diff --git a/ruby/ql/test/library-tests/dataflow/call-sensitivity/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/dataflow/call-sensitivity/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..8861088fef5b --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/call-sensitivity/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| call_sensitivity.rb:75:20:77:7 | do ... end | call_sensitivity.rb:74:15:74:15 | x | +| call_sensitivity.rb:75:20:77:7 | do ... end | call_sensitivity.rb:74:18:74:18 | y | diff --git a/ruby/ql/test/library-tests/dataflow/global/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/dataflow/global/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..b454f80cd36f --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/global/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,85 @@ +ambiguousReadNode +| captured_variables.rb:10:5:10:23 | ... = ... | captured_variables.rb:9:1:12:3 | self | +| captured_variables.rb:10:5:10:23 | ... = ... | captured_variables.rb:9:24:9:24 | x | +| captured_variables.rb:10:10:10:23 | -> { ... } | captured_variables.rb:9:1:12:3 | self | +| captured_variables.rb:10:10:10:23 | -> { ... } | captured_variables.rb:9:24:9:24 | x | +| captured_variables.rb:11:5:11:6 | fn | captured_variables.rb:9:1:12:3 | self | +| captured_variables.rb:11:5:11:6 | fn | captured_variables.rb:9:24:9:24 | x | +| captured_variables.rb:16:5:18:5 | -> { ... } | captured_variables.rb:15:1:19:3 | self | +| captured_variables.rb:16:5:18:5 | -> { ... } | captured_variables.rb:15:28:15:28 | x | +| captured_variables.rb:16:5:18:5 | ... | captured_variables.rb:15:1:19:3 | self | +| captured_variables.rb:16:5:18:5 | ... | captured_variables.rb:15:28:15:28 | x | +| captured_variables.rb:23:5:25:5 | -> { ... } | captured_variables.rb:22:1:26:3 | self | +| captured_variables.rb:23:5:25:5 | -> { ... } | captured_variables.rb:22:28:22:28 | x | +| captured_variables.rb:23:5:25:5 | ... | captured_variables.rb:22:1:26:3 | self | +| captured_variables.rb:23:5:25:5 | ... | captured_variables.rb:22:28:22:28 | x | +| captured_variables.rb:30:5:32:5 | ... = ... | captured_variables.rb:29:1:34:3 | self | +| captured_variables.rb:30:5:32:5 | ... = ... | captured_variables.rb:29:33:29:33 | x | +| captured_variables.rb:30:10:32:5 | -> { ... } | captured_variables.rb:29:1:34:3 | self | +| captured_variables.rb:30:10:32:5 | -> { ... } | captured_variables.rb:29:33:29:33 | x | +| captured_variables.rb:33:29:33:30 | fn | captured_variables.rb:29:1:34:3 | self | +| captured_variables.rb:33:29:33:30 | fn | captured_variables.rb:29:33:29:33 | x | +| captured_variables.rb:41:5:43:5 | ... = ... | captured_variables.rb:40:1:45:3 | self | +| captured_variables.rb:41:5:43:5 | ... = ... | captured_variables.rb:40:31:40:31 | x | +| captured_variables.rb:41:10:43:5 | -> { ... } | captured_variables.rb:40:1:45:3 | self | +| captured_variables.rb:41:10:43:5 | -> { ... } | captured_variables.rb:40:31:40:31 | x | +| captured_variables.rb:44:13:44:14 | fn | captured_variables.rb:40:1:45:3 | self | +| captured_variables.rb:44:13:44:14 | fn | captured_variables.rb:40:31:40:31 | x | +| captured_variables.rb:49:16:52:3 | do ... end | captured_variables.rb:1:1:244:2 | self | +| captured_variables.rb:49:16:52:3 | do ... end | captured_variables.rb:48:1:48:1 | x | +| captured_variables.rb:67:16:70:3 | do ... end | captured_variables.rb:1:1:244:2 | self | +| captured_variables.rb:67:16:70:3 | do ... end | captured_variables.rb:65:1:65:3 | foo | +| captured_variables.rb:78:20:80:7 | do ... end | captured_variables.rb:1:1:244:2 | self | +| captured_variables.rb:78:20:80:7 | do ... end | captured_variables.rb:65:1:65:3 | foo | +| captured_variables.rb:86:1:89:1 | ... = ... | captured_variables.rb:1:1:244:2 | self | +| captured_variables.rb:86:1:89:1 | ... = ... | captured_variables.rb:85:1:85:1 | y | +| captured_variables.rb:86:6:89:1 | -> { ... } | captured_variables.rb:1:1:244:2 | self | +| captured_variables.rb:86:6:89:1 | -> { ... } | captured_variables.rb:85:1:85:1 | y | +| captured_variables.rb:90:1:90:2 | fn | captured_variables.rb:1:1:244:2 | self | +| captured_variables.rb:90:1:90:2 | fn | captured_variables.rb:85:1:85:1 | y | +| captured_variables.rb:94:5:96:5 | -> { ... } | captured_variables.rb:93:1:97:3 | self | +| captured_variables.rb:94:5:96:5 | -> { ... } | captured_variables.rb:93:17:93:17 | x | +| captured_variables.rb:94:5:96:5 | ... | captured_variables.rb:93:1:97:3 | self | +| captured_variables.rb:94:5:96:5 | ... | captured_variables.rb:93:17:93:17 | x | +| captured_variables.rb:110:5:116:5 | ... = ... | captured_variables.rb:108:1:119:3 | self | +| captured_variables.rb:110:5:116:5 | ... = ... | captured_variables.rb:109:5:109:5 | x | +| captured_variables.rb:110:14:116:5 | -> { ... } | captured_variables.rb:108:1:119:3 | self | +| captured_variables.rb:110:14:116:5 | -> { ... } | captured_variables.rb:109:5:109:5 | x | +| captured_variables.rb:117:5:117:10 | middle | captured_variables.rb:108:1:119:3 | self | +| captured_variables.rb:117:5:117:10 | middle | captured_variables.rb:109:5:109:5 | x | +| captured_variables.rb:125:5:127:5 | ... = ... | captured_variables.rb:122:1:142:3 | self | +| captured_variables.rb:125:5:127:5 | ... = ... | captured_variables.rb:123:5:123:5 | x | +| captured_variables.rb:125:11:127:5 | -> { ... } | captured_variables.rb:122:1:142:3 | self | +| captured_variables.rb:125:11:127:5 | -> { ... } | captured_variables.rb:123:5:123:5 | x | +| captured_variables.rb:129:5:137:5 | ... = ... | captured_variables.rb:122:1:142:3 | self | +| captured_variables.rb:129:5:137:5 | ... = ... | captured_variables.rb:123:5:123:5 | x | +| captured_variables.rb:129:11:137:5 | -> { ... } | captured_variables.rb:122:1:142:3 | self | +| captured_variables.rb:129:11:137:5 | -> { ... } | captured_variables.rb:123:5:123:5 | x | +| captured_variables.rb:130:9:136:11 | ... | captured_variables.rb:129:11:137:5 | this | +| captured_variables.rb:130:9:136:11 | ... | captured_variables.rb:130:9:130:9 | y | +| captured_variables.rb:132:9:134:9 | ... = ... | captured_variables.rb:129:11:137:5 | this | +| captured_variables.rb:132:9:134:9 | ... = ... | captured_variables.rb:130:9:130:9 | y | +| captured_variables.rb:132:15:134:9 | -> { ... } | captured_variables.rb:129:11:137:5 | this | +| captured_variables.rb:132:15:134:9 | -> { ... } | captured_variables.rb:130:9:130:9 | y | +| captured_variables.rb:139:11:139:13 | fn3 | captured_variables.rb:122:1:142:3 | self | +| captured_variables.rb:139:11:139:13 | fn3 | captured_variables.rb:123:5:123:5 | x | +| captured_variables.rb:141:5:141:7 | fn1 | captured_variables.rb:122:1:142:3 | self | +| captured_variables.rb:141:5:141:7 | fn1 | captured_variables.rb:123:5:123:5 | x | +| captured_variables.rb:205:5:213:5 | ... = ... | captured_variables.rb:196:1:216:3 | self | +| captured_variables.rb:205:5:213:5 | ... = ... | captured_variables.rb:197:5:197:5 | x | +| captured_variables.rb:205:10:213:5 | -> { ... } | captured_variables.rb:196:1:216:3 | self | +| captured_variables.rb:205:10:213:5 | -> { ... } | captured_variables.rb:197:5:197:5 | x | +| captured_variables.rb:215:5:215:6 | fn | captured_variables.rb:196:1:216:3 | self | +| captured_variables.rb:215:5:215:6 | fn | captured_variables.rb:197:5:197:5 | x | +| captured_variables.rb:222:5:224:5 | ... = ... | captured_variables.rb:219:5:219:5 | x | +| captured_variables.rb:222:5:224:5 | ... = ... | captured_variables.rb:220:5:220:5 | y | +| captured_variables.rb:222:11:224:5 | -> { ... } | captured_variables.rb:219:5:219:5 | x | +| captured_variables.rb:222:11:224:5 | -> { ... } | captured_variables.rb:220:5:220:5 | y | +| captured_variables.rb:226:5:226:7 | fn1 | captured_variables.rb:219:5:219:5 | x | +| captured_variables.rb:226:5:226:7 | fn1 | captured_variables.rb:220:5:220:5 | y | +| captured_variables.rb:235:5:237:5 | ... = ... | captured_variables.rb:232:1:242:3 | self | +| captured_variables.rb:235:5:237:5 | ... = ... | captured_variables.rb:233:5:233:5 | x | +| captured_variables.rb:235:11:237:5 | -> { ... } | captured_variables.rb:232:1:242:3 | self | +| captured_variables.rb:235:11:237:5 | -> { ... } | captured_variables.rb:233:5:233:5 | x | +| captured_variables.rb:241:5:241:7 | fn1 | captured_variables.rb:232:1:242:3 | self | +| captured_variables.rb:241:5:241:7 | fn1 | captured_variables.rb:233:5:233:5 | x | diff --git a/ruby/ql/test/library-tests/dataflow/local/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/dataflow/local/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..7a65959a07bb --- /dev/null +++ b/ruby/ql/test/library-tests/dataflow/local/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| local_dataflow.rb:10:5:13:3 | { ... } | local_dataflow.rb:1:1:174:4 | self | +| local_dataflow.rb:10:5:13:3 | { ... } | local_dataflow.rb:10:9:10:9 | x | diff --git a/ruby/ql/test/library-tests/frameworks/action_view/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/frameworks/action_view/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..df37e38d506f --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_view/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| app/views/foo/bars/show.html.erb:10:37:12:6 | do ... end | app/views/foo/bars/show.html.erb:1:14:33:43 | self | +| app/views/foo/bars/show.html.erb:10:37:12:6 | do ... end | app/views/foo/bars/show.html.erb:6:4:6:6 | key | diff --git a/ruby/ql/test/library-tests/frameworks/rack/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/frameworks/rack/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..8fd7077be5e1 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/rack/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,6 @@ +ambiguousReadNode +| rack.rb:34:32:34:69 | { ... } | rack.rb:30:3:36:5 | self | +| rack.rb:34:32:34:69 | { ... } | rack.rb:30:12:30:14 | env | +| rack.rb:34:32:34:69 | { ... } | rack.rb:31:5:31:12 | began_at | +| rack.rb:34:32:34:69 | { ... } | rack.rb:32:5:32:10 | status | +| rack.rb:34:32:34:69 | { ... } | rack.rb:32:13:32:18 | header | diff --git a/ruby/ql/test/library-tests/frameworks/sinatra/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/frameworks/sinatra/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..528b95a4a187 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/sinatra/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| app.rb:64:41:64:57 | { ... } | app.rb:64:21:64:59 | this | +| app.rb:64:41:64:57 | { ... } | app.rb:64:24:64:28 | value | diff --git a/ruby/ql/test/library-tests/modules/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/modules/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..fa3f6afe3fad --- /dev/null +++ b/ruby/ql/test/library-tests/modules/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| calls.rb:492:35:494:11 | do ... end | calls.rb:491:18:495:7 | this | +| calls.rb:492:35:494:11 | do ... end | calls.rb:491:22:491:22 | i | diff --git a/ruby/ql/test/library-tests/variables/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/variables/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..6c2cca383f88 --- /dev/null +++ b/ruby/ql/test/library-tests/variables/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,15 @@ +ambiguousReadNode +| nested_scopes.rb:18:23:18:36 | { ... } | nested_scopes.rb:16:21:19:15 | this | +| nested_scopes.rb:18:23:18:36 | { ... } | nested_scopes.rb:16:29:16:29 | a | +| parameters.rb:54:9:57:3 | do ... end | parameters.rb:1:1:62:1 | self | +| parameters.rb:54:9:57:3 | do ... end | parameters.rb:53:1:53:1 | x | +| scopes.rb:9:9:18:3 | do ... end | scopes.rb:1:1:89:4 | self | +| scopes.rb:9:9:18:3 | do ... end | scopes.rb:7:1:7:1 | a | +| ssa.rb:26:3:28:5 | { ... } | ssa.rb:25:1:30:3 | self | +| ssa.rb:26:3:28:5 | { ... } | ssa.rb:26:7:26:10 | elem | +| ssa.rb:66:11:70:5 | do ... end | ssa.rb:64:1:72:3 | self | +| ssa.rb:66:11:70:5 | do ... end | ssa.rb:65:3:65:10 | captured | +| ssa.rb:76:7:78:5 | do ... end | ssa.rb:74:1:79:3 | self | +| ssa.rb:76:7:78:5 | do ... end | ssa.rb:75:3:75:10 | captured | +| ssa.rb:83:7:87:5 | do ... end | ssa.rb:81:1:88:3 | self | +| ssa.rb:83:7:87:5 | do ... end | ssa.rb:82:3:82:10 | captured | diff --git a/ruby/ql/test/query-tests/experimental/InsecureRandomness/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/experimental/InsecureRandomness/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..bc17a7c2a860 --- /dev/null +++ b/ruby/ql/test/query-tests/experimental/InsecureRandomness/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| InsecureRandomness.rb:6:34:6:60 | { ... } | InsecureRandomness.rb:3:1:7:3 | self | +| InsecureRandomness.rb:6:34:6:60 | { ... } | InsecureRandomness.rb:4:3:4:7 | chars | diff --git a/ruby/ql/test/query-tests/experimental/improper-memoization/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/experimental/improper-memoization/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..19f2d36a5fd6 --- /dev/null +++ b/ruby/ql/test/query-tests/experimental/improper-memoization/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,5 @@ +ambiguousReadNode +| improper_memoization.rb:42:25:44:7 | do ... end | improper_memoization.rb:41:20:45:5 | this | +| improper_memoization.rb:42:25:44:7 | do ... end | improper_memoization.rb:41:28:41:31 | arg1 | +| improper_memoization.rb:83:21:85:5 | do ... end | improper_memoization.rb:82:1:87:3 | self | +| improper_memoization.rb:83:21:85:5 | do ... end | improper_memoization.rb:82:15:82:18 | arg2 | diff --git a/ruby/ql/test/query-tests/security/cwe-079/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/security/cwe-079/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..f595abd76408 --- /dev/null +++ b/ruby/ql/test/query-tests/security/cwe-079/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,5 @@ +ambiguousReadNode +| app/views/foo/bars/show.html.erb:15:4:18:6 | { ... } | app/views/foo/bars/show.html.erb:2:14:89:48 | self | +| app/views/foo/bars/show.html.erb:15:4:18:6 | { ... } | app/views/foo/bars/show.html.erb:10:4:10:6 | key | +| app/views/foo/stores/show.html.erb:12:4:15:6 | { ... } | app/views/foo/stores/show.html.erb:2:5:90:48 | self | +| app/views/foo/stores/show.html.erb:12:4:15:6 | { ... } | app/views/foo/stores/show.html.erb:7:4:7:6 | key | diff --git a/ruby/ql/test/query-tests/variables/DeadStoreOfLocal/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/variables/DeadStoreOfLocal/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..e9dd3ea8adfe --- /dev/null +++ b/ruby/ql/test/query-tests/variables/DeadStoreOfLocal/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,5 @@ +ambiguousReadNode +| DeadStoreOfLocal.rb:44:14:47:7 | do ... end | DeadStoreOfLocal.rb:43:1:48:3 | self | +| DeadStoreOfLocal.rb:44:14:47:7 | do ... end | DeadStoreOfLocal.rb:43:20:43:20 | x | +| DeadStoreOfLocal.rb:57:16:65:7 | do ... end | DeadStoreOfLocal.rb:56:1:66:3 | self | +| DeadStoreOfLocal.rb:57:16:65:7 | do ... end | DeadStoreOfLocal.rb:56:17:56:17 | x | diff --git a/ruby/ql/test/query-tests/variables/UninitializedLocal/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/variables/UninitializedLocal/CONSISTENCY/VariablesConsistency.expected new file mode 100644 index 000000000000..4193d87746f6 --- /dev/null +++ b/ruby/ql/test/query-tests/variables/UninitializedLocal/CONSISTENCY/VariablesConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| UninitializedLocal.rb:73:5:75:7 | { ... } | UninitializedLocal.rb:72:1:77:3 | self | +| UninitializedLocal.rb:73:5:75:7 | { ... } | UninitializedLocal.rb:73:9:73:9 | i | diff --git a/rust/ql/test/library-tests/controlflow/CONSISTENCY/VariableCaptureConsistency.expected b/rust/ql/test/library-tests/controlflow/CONSISTENCY/VariableCaptureConsistency.expected new file mode 100644 index 000000000000..87bc24d5e5a6 --- /dev/null +++ b/rust/ql/test/library-tests/controlflow/CONSISTENCY/VariableCaptureConsistency.expected @@ -0,0 +1,3 @@ +ambiguousReadNode +| test.rs:511:28:516:9 | { ... } | test.rs:511:22:516:9 | this | +| test.rs:511:28:516:9 | { ... } | test.rs:511:23:511:25 | foo | diff --git a/rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/VariableCaptureConsistency.expected b/rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/VariableCaptureConsistency.expected new file mode 100644 index 000000000000..b8abfaf72c0e --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/VariableCaptureConsistency.expected @@ -0,0 +1,17 @@ +ambiguousReadNode +| lifetime.rs:514:2:527:2 | return ... | lifetime.rs:509:16:509:17 | p3 | +| lifetime.rs:514:2:527:2 | return ... | lifetime.rs:509:32:509:33 | p4 | +| lifetime.rs:514:2:527:2 | return ... | lifetime.rs:511:6:511:14 | my_local2 | +| lifetime.rs:514:2:527:2 | return ... | lifetime.rs:512:6:512:7 | p1 | +| lifetime.rs:514:9:527:2 | \|...\| ... | lifetime.rs:509:16:509:17 | p3 | +| lifetime.rs:514:9:527:2 | \|...\| ... | lifetime.rs:509:32:509:33 | p4 | +| lifetime.rs:514:9:527:2 | \|...\| ... | lifetime.rs:511:6:511:14 | my_local2 | +| lifetime.rs:514:9:527:2 | \|...\| ... | lifetime.rs:512:6:512:7 | p1 | +| lifetime.rs:567:2:580:2 | return ... | lifetime.rs:562:22:562:23 | p3 | +| lifetime.rs:567:2:580:2 | return ... | lifetime.rs:562:38:562:39 | p4 | +| lifetime.rs:567:2:580:2 | return ... | lifetime.rs:564:6:564:14 | my_local2 | +| lifetime.rs:567:2:580:2 | return ... | lifetime.rs:565:6:565:7 | p1 | +| lifetime.rs:567:9:580:2 | { ... } | lifetime.rs:562:22:562:23 | p3 | +| lifetime.rs:567:9:580:2 | { ... } | lifetime.rs:562:38:562:39 | p4 | +| lifetime.rs:567:9:580:2 | { ... } | lifetime.rs:564:6:564:14 | my_local2 | +| lifetime.rs:567:9:580:2 | { ... } | lifetime.rs:565:6:565:7 | p1 | From 8957cdae1a4aad59ab3597ebaa6c6d3fc02e9280 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 12:47:30 +0200 Subject: [PATCH 06/40] ssa: Associate ExprNode with a variable --- shared/ssa/codeql/ssa/Ssa.qll | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/shared/ssa/codeql/ssa/Ssa.qll b/shared/ssa/codeql/ssa/Ssa.qll index 151728da5466..7f05e5c006a1 100644 --- a/shared/ssa/codeql/ssa/Ssa.qll +++ b/shared/ssa/codeql/ssa/Ssa.qll @@ -1680,7 +1680,12 @@ module Make< cached private newtype TNode = TWriteDefSource(WriteDefinition def) { DfInput::ssaDefHasSource(def) } or - TExprNode(DfInput::Expr e, Boolean isPost) { e = DfInput::getARead(_) } or + TExprNode(DfInput::Expr e, SourceVariable v, Boolean isPost) { + exists(Definition def | + def.getSourceVariable() = v and + e = DfInput::getARead(def) + ) + } or TSsaDefinitionNode(DefinitionExt def) { not phiHasUniqNextNode(def) and if DfInput::includeWriteDefsInFlowStep() @@ -1730,8 +1735,9 @@ module Make< abstract private class ExprNodePreOrPostImpl extends NodeImpl, TExprNode { DfInput::Expr e; boolean isPost; + SourceVariable v_; - ExprNodePreOrPostImpl() { this = TExprNode(e, isPost) } + ExprNodePreOrPostImpl() { this = TExprNode(e, v_, isPost) } /** Gets the underlying expression. */ DfInput::Expr getExpr() { result = e } @@ -1742,6 +1748,9 @@ module Make< result = bb.getNode(i).getLocation() ) } + + /** Gets the variable accessed at this expression. */ + SourceVariable getSourceVariable() { result = v_ } } final class ExprNodePreOrPost = ExprNodePreOrPostImpl; @@ -1760,7 +1769,7 @@ module Make< ExprPostUpdateNodeImpl() { isPost = true } /** Gets the pre-update expression node. */ - ExprNode getPreUpdateNode() { result = TExprNode(e, false) } + ExprNode getPreUpdateNode() { result = TExprNode(e, _, false) } override string toString() { result = e.toString() + " [postupdate]" } } @@ -1770,7 +1779,6 @@ module Make< private class ReadNodeImpl extends ExprNodeImpl { private BasicBlock bb_; private int i_; - private SourceVariable v_; ReadNodeImpl() { variableRead(bb_, i_, v_, true) and From c0847078f27d4c1fad89aeb69fe21ad686e16488 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 16:13:11 +0200 Subject: [PATCH 07/40] ssa: Record absense of ambiguousReadNode errors The previously-added consistency errors are gone. --- .../VariableCaptureConsistency.expected | 39 --------- .../VariableCaptureConsistency.expected | 17 ---- .../VariableCaptureConsistency.expected | 23 ----- .../VariableCaptureConsistency.expected | 5 -- .../VariableCaptureConsistency.expected | 3 - .../VariableCaptureConsistency.expected | 9 -- .../dataflow-capture-consistency.expected | 28 ------ .../CONSISTENCY/VariablesConsistency.expected | 27 ------ .../CONSISTENCY/VariablesConsistency.expected | 11 --- .../CONSISTENCY/VariablesConsistency.expected | 15 ---- .../CONSISTENCY/VariablesConsistency.expected | 3 - .../CONSISTENCY/VariablesConsistency.expected | 5 -- .../CONSISTENCY/VariablesConsistency.expected | 3 - .../CONSISTENCY/VariablesConsistency.expected | 3 - .../CONSISTENCY/VariablesConsistency.expected | 85 ------------------- .../CONSISTENCY/VariablesConsistency.expected | 3 - .../CONSISTENCY/VariablesConsistency.expected | 3 - .../CONSISTENCY/VariablesConsistency.expected | 6 -- .../CONSISTENCY/VariablesConsistency.expected | 3 - .../CONSISTENCY/VariablesConsistency.expected | 3 - .../CONSISTENCY/VariablesConsistency.expected | 15 ---- .../CONSISTENCY/VariablesConsistency.expected | 3 - .../CONSISTENCY/VariablesConsistency.expected | 5 -- .../CONSISTENCY/VariablesConsistency.expected | 5 -- .../CONSISTENCY/VariablesConsistency.expected | 5 -- .../CONSISTENCY/VariablesConsistency.expected | 3 - .../VariableCaptureConsistency.expected | 3 - .../VariableCaptureConsistency.expected | 17 ---- 28 files changed, 350 deletions(-) delete mode 100644 csharp/ql/test/library-tests/dataflow/global/CONSISTENCY/VariableCaptureConsistency.expected delete mode 100644 csharp/ql/test/library-tests/dataflow/local/CONSISTENCY/VariableCaptureConsistency.expected delete mode 100644 csharp/ql/test/library-tests/dataflow/ssa/CONSISTENCY/VariableCaptureConsistency.expected delete mode 100644 csharp/ql/test/query-tests/Likely Bugs/ThreadUnsafeICryptoTransformLambda/CONSISTENCY/VariableCaptureConsistency.expected delete mode 100644 csharp/ql/test/query-tests/Nullness/CONSISTENCY/VariableCaptureConsistency.expected delete mode 100644 csharp/ql/test/query-tests/standalone/Language Abuse/SimplifyBoolExpr/CONSISTENCY/VariableCaptureConsistency.expected delete mode 100644 ruby/ql/test/library-tests/ast/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/ast/calls/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/ast/control/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/ast/erb/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/controlflow/graph/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/dataflow/array-flow/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/dataflow/call-sensitivity/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/dataflow/global/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/dataflow/local/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/frameworks/action_view/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/frameworks/rack/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/frameworks/sinatra/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/modules/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/library-tests/variables/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/query-tests/experimental/InsecureRandomness/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/query-tests/experimental/improper-memoization/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/query-tests/security/cwe-079/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/query-tests/variables/DeadStoreOfLocal/CONSISTENCY/VariablesConsistency.expected delete mode 100644 ruby/ql/test/query-tests/variables/UninitializedLocal/CONSISTENCY/VariablesConsistency.expected delete mode 100644 rust/ql/test/library-tests/controlflow/CONSISTENCY/VariableCaptureConsistency.expected delete mode 100644 rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/VariableCaptureConsistency.expected diff --git a/csharp/ql/test/library-tests/dataflow/global/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/library-tests/dataflow/global/CONSISTENCY/VariableCaptureConsistency.expected deleted file mode 100644 index 938ee32c47d1..000000000000 --- a/csharp/ql/test/library-tests/dataflow/global/CONSISTENCY/VariableCaptureConsistency.expected +++ /dev/null @@ -1,39 +0,0 @@ -ambiguousReadNode -| Capture.cs:16:9:24:9 | CaptureIn2(...) | Capture.cs:7:10:7:11 | this in In | -| Capture.cs:16:9:24:9 | CaptureIn2(...) | Capture.cs:7:20:7:26 | tainted | -| Capture.cs:25:9:25:18 | access to local function CaptureIn2 | Capture.cs:7:10:7:11 | this in In | -| Capture.cs:25:9:25:18 | access to local function CaptureIn2 | Capture.cs:7:20:7:26 | tainted | -| Capture.cs:52:23:59:13 | (...) => ... | Capture.cs:50:33:50:40 | nonSink0 | -| Capture.cs:52:23:59:13 | (...) => ... | Capture.cs:50:50:50:55 | sink39 | -| Capture.cs:75:9:82:9 | CaptureOut2(...) | Capture.cs:64:10:64:12 | this in Out | -| Capture.cs:75:9:82:9 | CaptureOut2(...) | Capture.cs:74:16:74:21 | sink31 | -| Capture.cs:83:9:83:19 | access to local function CaptureOut2 | Capture.cs:64:10:64:12 | this in Out | -| Capture.cs:83:9:83:19 | access to local function CaptureOut2 | Capture.cs:74:16:74:21 | sink31 | -| Capture.cs:112:9:122:9 | CaptureOutMultipleLambdas(...) | Capture.cs:95:16:95:23 | nonSink0 | -| Capture.cs:112:9:122:9 | CaptureOutMultipleLambdas(...) | Capture.cs:111:16:111:21 | sink40 | -| Capture.cs:123:9:123:33 | access to local function CaptureOutMultipleLambdas | Capture.cs:95:16:95:23 | nonSink0 | -| Capture.cs:123:9:123:33 | access to local function CaptureOutMultipleLambdas | Capture.cs:111:16:111:21 | sink40 | -| Capture.cs:130:9:133:9 | CaptureThrough1(...) | Capture.cs:127:25:127:31 | tainted | -| Capture.cs:130:9:133:9 | CaptureThrough1(...) | Capture.cs:129:16:129:21 | sink33 | -| Capture.cs:134:9:134:23 | access to local function CaptureThrough1 | Capture.cs:127:25:127:31 | tainted | -| Capture.cs:134:9:134:23 | access to local function CaptureThrough1 | Capture.cs:129:16:129:21 | sink33 | -| Capture.cs:138:9:145:9 | CaptureThrough2(...) | Capture.cs:127:10:127:16 | this in Through | -| Capture.cs:138:9:145:9 | CaptureThrough2(...) | Capture.cs:127:25:127:31 | tainted | -| Capture.cs:138:9:145:9 | CaptureThrough2(...) | Capture.cs:137:16:137:21 | sink34 | -| Capture.cs:146:9:146:23 | access to local function CaptureThrough2 | Capture.cs:127:10:127:16 | this in Through | -| Capture.cs:146:9:146:23 | access to local function CaptureThrough2 | Capture.cs:127:25:127:31 | tainted | -| Capture.cs:146:9:146:23 | access to local function CaptureThrough2 | Capture.cs:137:16:137:21 | sink34 | -| Capture.cs:150:48:154:9 | (...) => ... | Capture.cs:127:25:127:31 | tainted | -| Capture.cs:150:48:154:9 | (...) => ... | Capture.cs:149:16:149:21 | sink35 | -| Capture.cs:155:30:155:44 | access to local variable captureThrough3 | Capture.cs:127:25:127:31 | tainted | -| Capture.cs:155:30:155:44 | access to local variable captureThrough3 | Capture.cs:149:16:149:21 | sink35 | -| Capture.cs:174:9:177:9 | CaptureThrough1NotCalled(...) | Capture.cs:127:25:127:31 | tainted | -| Capture.cs:174:9:177:9 | CaptureThrough1NotCalled(...) | Capture.cs:173:16:173:23 | nonSink0 | -| Capture.cs:180:9:186:9 | CaptureThrough2NotCalled(...) | Capture.cs:127:25:127:31 | tainted | -| Capture.cs:180:9:186:9 | CaptureThrough2NotCalled(...) | Capture.cs:173:16:173:23 | nonSink0 | -| Capture.cs:187:9:187:32 | access to local function CaptureThrough2NotCalled | Capture.cs:127:25:127:31 | tainted | -| Capture.cs:187:9:187:32 | access to local function CaptureThrough2NotCalled | Capture.cs:173:16:173:23 | nonSink0 | -| Capture.cs:332:9:332:65 | CapturingLocalFunction(...) | Capture.cs:326:10:326:12 | this in M12 | -| Capture.cs:332:9:332:65 | CapturingLocalFunction(...) | Capture.cs:328:13:328:13 | x | -| Capture.cs:334:9:334:30 | access to local function CapturingLocalFunction | Capture.cs:326:10:326:12 | this in M12 | -| Capture.cs:334:9:334:30 | access to local function CapturingLocalFunction | Capture.cs:328:13:328:13 | x | diff --git a/csharp/ql/test/library-tests/dataflow/local/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/library-tests/dataflow/local/CONSISTENCY/VariableCaptureConsistency.expected deleted file mode 100644 index b790fa24b23f..000000000000 --- a/csharp/ql/test/library-tests/dataflow/local/CONSISTENCY/VariableCaptureConsistency.expected +++ /dev/null @@ -1,17 +0,0 @@ -ambiguousReadNode -| Capture.cs:15:9:22:9 | CapIn2(...) | Capture.cs:5:17:5:17 | this in M | -| Capture.cs:15:9:22:9 | CapIn2(...) | Capture.cs:7:13:7:13 | i | -| Capture.cs:23:9:23:14 | access to local function CapIn2 | Capture.cs:5:17:5:17 | this in M | -| Capture.cs:23:9:23:14 | access to local function CapIn2 | Capture.cs:7:13:7:13 | i | -| Capture.cs:25:9:33:9 | CapIn4(...) | Capture.cs:5:17:5:17 | this in M | -| Capture.cs:25:9:33:9 | CapIn4(...) | Capture.cs:7:13:7:13 | i | -| Capture.cs:34:9:34:14 | access to local function CapIn4 | Capture.cs:5:17:5:17 | this in M | -| Capture.cs:34:9:34:14 | access to local function CapIn4 | Capture.cs:7:13:7:13 | i | -| Capture.cs:43:9:50:9 | CapOut2(...) | Capture.cs:5:17:5:17 | this in M | -| Capture.cs:43:9:50:9 | CapOut2(...) | Capture.cs:7:13:7:13 | i | -| Capture.cs:51:9:51:15 | access to local function CapOut2 | Capture.cs:5:17:5:17 | this in M | -| Capture.cs:51:9:51:15 | access to local function CapOut2 | Capture.cs:7:13:7:13 | i | -| Capture.cs:54:9:62:9 | CapOut4(...) | Capture.cs:5:17:5:17 | this in M | -| Capture.cs:54:9:62:9 | CapOut4(...) | Capture.cs:7:13:7:13 | i | -| Capture.cs:63:9:63:15 | access to local function CapOut4 | Capture.cs:5:17:5:17 | this in M | -| Capture.cs:63:9:63:15 | access to local function CapOut4 | Capture.cs:7:13:7:13 | i | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/library-tests/dataflow/ssa/CONSISTENCY/VariableCaptureConsistency.expected deleted file mode 100644 index f3c4bb63106d..000000000000 --- a/csharp/ql/test/library-tests/dataflow/ssa/CONSISTENCY/VariableCaptureConsistency.expected +++ /dev/null @@ -1,23 +0,0 @@ -ambiguousReadNode -| Capture.cs:10:20:27:9 | (...) => ... | Capture.cs:6:16:6:16 | i | -| Capture.cs:10:20:27:9 | (...) => ... | Capture.cs:8:13:8:13 | x | -| Capture.cs:19:24:23:13 | (...) => ... | Capture.cs:10:20:27:9 | this | -| Capture.cs:19:24:23:13 | (...) => ... | Capture.cs:17:17:17:17 | y | -| Capture.cs:25:13:25:13 | access to local variable b | Capture.cs:10:20:27:9 | this | -| Capture.cs:25:13:25:13 | access to local variable b | Capture.cs:17:17:17:17 | y | -| Capture.cs:38:9:38:9 | access to local variable a | Capture.cs:6:16:6:16 | i | -| Capture.cs:38:9:38:9 | access to local variable a | Capture.cs:8:13:8:13 | x | -| Capture.cs:46:12:46:12 | access to local variable a | Capture.cs:6:16:6:16 | i | -| Capture.cs:46:12:46:12 | access to local variable a | Capture.cs:8:13:8:13 | x | -| Capture.cs:169:9:178:9 | M8(...) | Capture.cs:112:10:112:28 | this in NestedFunctionsTest | -| Capture.cs:169:9:178:9 | M8(...) | Capture.cs:168:13:168:13 | h | -| Capture.cs:248:9:252:9 | CaptureAndRef(...) | Capture.cs:240:10:240:11 | this in M2 | -| Capture.cs:248:9:252:9 | CaptureAndRef(...) | Capture.cs:242:13:242:13 | i | -| Capture.cs:254:9:254:21 | access to local function CaptureAndRef | Capture.cs:240:10:240:11 | this in M2 | -| Capture.cs:254:9:254:21 | access to local function CaptureAndRef | Capture.cs:242:13:242:13 | i | -| Consistency.cs:39:20:39:43 | (...) => ... | Consistency.cs:36:10:36:27 | this in CapturedDeclNoInit | -| Consistency.cs:39:20:39:43 | (...) => ... | Consistency.cs:38:13:38:13 | i | -| Fields.cs:81:9:81:9 | access to local variable a | Fields.cs:77:13:77:13 | f | -| Fields.cs:81:9:81:9 | access to local variable a | Fields.cs:78:23:78:23 | a | -| Properties.cs:77:9:77:9 | access to local variable a | Properties.cs:73:13:73:13 | f | -| Properties.cs:77:9:77:9 | access to local variable a | Properties.cs:74:23:74:23 | a | diff --git a/csharp/ql/test/query-tests/Likely Bugs/ThreadUnsafeICryptoTransformLambda/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/query-tests/Likely Bugs/ThreadUnsafeICryptoTransformLambda/CONSISTENCY/VariableCaptureConsistency.expected deleted file mode 100644 index becc963c0fe5..000000000000 --- a/csharp/ql/test/query-tests/Likely Bugs/ThreadUnsafeICryptoTransformLambda/CONSISTENCY/VariableCaptureConsistency.expected +++ /dev/null @@ -1,5 +0,0 @@ -ambiguousReadNode -| ThreadUnsafeICryptoTransformLambda.cs:16:24:22:9 | (...) => ... | ThreadUnsafeICryptoTransformLambda.cs:10:32:10:34 | max | -| ThreadUnsafeICryptoTransformLambda.cs:16:24:22:9 | (...) => ... | ThreadUnsafeICryptoTransformLambda.cs:15:13:15:16 | sha1 | -| ThreadUnsafeICryptoTransformLambda.cs:80:24:86:9 | (...) => ... | ThreadUnsafeICryptoTransformLambda.cs:73:32:73:34 | max | -| ThreadUnsafeICryptoTransformLambda.cs:80:24:86:9 | (...) => ... | ThreadUnsafeICryptoTransformLambda.cs:77:13:77:16 | sha1 | diff --git a/csharp/ql/test/query-tests/Nullness/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/query-tests/Nullness/CONSISTENCY/VariableCaptureConsistency.expected deleted file mode 100644 index 4bbdd3f461de..000000000000 --- a/csharp/ql/test/query-tests/Nullness/CONSISTENCY/VariableCaptureConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| A.cs:61:31:61:45 | (...) => ... | A.cs:61:26:61:26 | e | -| A.cs:61:31:61:45 | (...) => ... | A.cs:61:26:61:45 | this | diff --git a/csharp/ql/test/query-tests/standalone/Language Abuse/SimplifyBoolExpr/CONSISTENCY/VariableCaptureConsistency.expected b/csharp/ql/test/query-tests/standalone/Language Abuse/SimplifyBoolExpr/CONSISTENCY/VariableCaptureConsistency.expected deleted file mode 100644 index bc7a35a116b4..000000000000 --- a/csharp/ql/test/query-tests/standalone/Language Abuse/SimplifyBoolExpr/CONSISTENCY/VariableCaptureConsistency.expected +++ /dev/null @@ -1,9 +0,0 @@ -ambiguousReadNode -| SimplifyBoolExpr.cs:53:29:53:50 | (...) => ... | SimplifyBoolExpr.cs:50:65:50:68 | left | -| SimplifyBoolExpr.cs:53:29:53:50 | (...) => ... | SimplifyBoolExpr.cs:50:100:50:104 | right | -| SimplifyBoolExpr.cs:56:9:56:41 | Local(...) | SimplifyBoolExpr.cs:50:65:50:68 | left | -| SimplifyBoolExpr.cs:56:9:56:41 | Local(...) | SimplifyBoolExpr.cs:50:100:50:104 | right | -| SimplifyBoolExpr.cs:58:16:58:21 | access to local variable lambda | SimplifyBoolExpr.cs:50:65:50:68 | left | -| SimplifyBoolExpr.cs:58:16:58:21 | access to local variable lambda | SimplifyBoolExpr.cs:50:100:50:104 | right | -| SimplifyBoolExpr.cs:58:28:58:32 | access to local function Local | SimplifyBoolExpr.cs:50:65:50:68 | left | -| SimplifyBoolExpr.cs:58:28:58:32 | access to local function Local | SimplifyBoolExpr.cs:50:100:50:104 | right | diff --git a/python/ql/test/library-tests/dataflow/variable-capture/dataflow-capture-consistency.expected b/python/ql/test/library-tests/dataflow/variable-capture/dataflow-capture-consistency.expected index 2837533cd483..e331f0ddde45 100644 --- a/python/ql/test/library-tests/dataflow/variable-capture/dataflow-capture-consistency.expected +++ b/python/ql/test/library-tests/dataflow/variable-capture/dataflow-capture-consistency.expected @@ -16,31 +16,3 @@ variableAccessAstNesting uniqueCallableLocation consistencyOverview ambiguousReadNode -| dict.py:67:5:67:22 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable sinkO1 | -| dict.py:67:5:67:22 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable tainted | -| dict.py:69:5:69:15 | ControlFlowNode for captureOut1 | dict.py:65:1:65:21 | Local Variable sinkO1 | -| dict.py:69:5:69:15 | ControlFlowNode for captureOut1 | dict.py:65:1:65:21 | Local Variable tainted | -| dict.py:73:5:73:22 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable sinkO2 | -| dict.py:73:5:73:22 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable tainted | -| dict.py:77:5:77:15 | ControlFlowNode for captureOut2 | dict.py:65:1:65:21 | Local Variable sinkO2 | -| dict.py:77:5:77:15 | ControlFlowNode for captureOut2 | dict.py:65:1:65:21 | Local Variable tainted | -| dict.py:81:5:81:31 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable nonSink1 | -| dict.py:81:5:81:31 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable tainted | -| dict.py:86:5:86:31 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable nonSink2 | -| dict.py:86:5:86:31 | ControlFlowNode for FunctionExpr | dict.py:65:1:65:21 | Local Variable tainted | -| dict.py:90:5:90:24 | ControlFlowNode for captureOut2NotCalled | dict.py:65:1:65:21 | Local Variable nonSink2 | -| dict.py:90:5:90:24 | ControlFlowNode for captureOut2NotCalled | dict.py:65:1:65:21 | Local Variable tainted | -| nonlocal.py:73:5:73:22 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable sinkO1 | -| nonlocal.py:73:5:73:22 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable tainted | -| nonlocal.py:76:5:76:15 | ControlFlowNode for captureOut1 | nonlocal.py:71:1:71:21 | Local Variable sinkO1 | -| nonlocal.py:76:5:76:15 | ControlFlowNode for captureOut1 | nonlocal.py:71:1:71:21 | Local Variable tainted | -| nonlocal.py:80:5:80:22 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable sinkO2 | -| nonlocal.py:80:5:80:22 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable tainted | -| nonlocal.py:85:5:85:15 | ControlFlowNode for captureOut2 | nonlocal.py:71:1:71:21 | Local Variable sinkO2 | -| nonlocal.py:85:5:85:15 | ControlFlowNode for captureOut2 | nonlocal.py:71:1:71:21 | Local Variable tainted | -| nonlocal.py:89:5:89:31 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable nonSink1 | -| nonlocal.py:89:5:89:31 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable tainted | -| nonlocal.py:95:5:95:31 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable nonSink2 | -| nonlocal.py:95:5:95:31 | ControlFlowNode for FunctionExpr | nonlocal.py:71:1:71:21 | Local Variable tainted | -| nonlocal.py:100:5:100:24 | ControlFlowNode for captureOut2NotCalled | nonlocal.py:71:1:71:21 | Local Variable nonSink2 | -| nonlocal.py:100:5:100:24 | ControlFlowNode for captureOut2NotCalled | nonlocal.py:71:1:71:21 | Local Variable tainted | diff --git a/ruby/ql/test/library-tests/ast/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/ast/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 9b218f507380..000000000000 --- a/ruby/ql/test/library-tests/ast/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,27 +0,0 @@ -ambiguousReadNode -| calls/calls.rb:223:1:225:3 | { ... } | calls/calls.rb:1:1:367:24 | self | -| calls/calls.rb:223:1:225:3 | { ... } | calls/calls.rb:223:5:223:5 | x | -| calls/calls.rb:343:1:345:3 | { ... } | calls/calls.rb:1:1:367:24 | self | -| calls/calls.rb:343:1:345:3 | { ... } | calls/calls.rb:223:5:223:5 | x | -| calls/calls.rb:343:1:345:3 | { ... } | calls/calls.rb:343:8:343:8 | y | -| calls/calls.rb:343:1:345:3 | { ... } | calls/calls.rb:343:11:343:11 | z | -| calls/calls.rb:357:1:361:3 | ... = ... | calls/calls.rb:1:1:367:24 | self | -| calls/calls.rb:357:1:361:3 | ... = ... | calls/calls.rb:343:8:343:8 | y | -| calls/calls.rb:357:5:361:3 | -> { ... } | calls/calls.rb:1:1:367:24 | self | -| calls/calls.rb:357:5:361:3 | -> { ... } | calls/calls.rb:343:8:343:8 | y | -| control/loops.rb:9:1:12:3 | { ... } | control/loops.rb:2:1:2:3 | foo | -| control/loops.rb:9:1:12:3 | { ... } | control/loops.rb:3:1:3:3 | sum | -| control/loops.rb:9:1:12:3 | { ... } | control/loops.rb:9:5:9:5 | n | -| control/loops.rb:16:1:19:3 | { ... } | control/loops.rb:2:1:2:3 | foo | -| control/loops.rb:16:1:19:3 | { ... } | control/loops.rb:3:1:3:3 | sum | -| control/loops.rb:16:1:19:3 | { ... } | control/loops.rb:9:5:9:5 | n | -| control/loops.rb:22:1:25:3 | { ... } | control/loops.rb:2:1:2:3 | foo | -| control/loops.rb:22:1:25:3 | { ... } | control/loops.rb:3:1:3:3 | sum | -| control/loops.rb:22:1:25:3 | { ... } | control/loops.rb:22:5:22:7 | key | -| control/loops.rb:22:1:25:3 | { ... } | control/loops.rb:22:10:22:14 | value | -| control/loops.rb:28:1:32:3 | { ... } | control/loops.rb:2:1:2:3 | foo | -| control/loops.rb:28:1:32:3 | { ... } | control/loops.rb:3:1:3:3 | sum | -| control/loops.rb:28:1:32:3 | { ... } | control/loops.rb:22:5:22:7 | key | -| control/loops.rb:28:1:32:3 | { ... } | control/loops.rb:22:10:22:14 | value | -| erb/template.html.erb:27:6:31:8 | { ... } | erb/template.html.erb:25:4:25:5 | xs | -| erb/template.html.erb:27:6:31:8 | { ... } | erb/template.html.erb:27:10:27:10 | x | diff --git a/ruby/ql/test/library-tests/ast/calls/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/ast/calls/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 7440cff458c8..000000000000 --- a/ruby/ql/test/library-tests/ast/calls/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,11 +0,0 @@ -ambiguousReadNode -| calls.rb:223:1:225:3 | { ... } | calls.rb:1:1:367:24 | self | -| calls.rb:223:1:225:3 | { ... } | calls.rb:223:5:223:5 | x | -| calls.rb:343:1:345:3 | { ... } | calls.rb:1:1:367:24 | self | -| calls.rb:343:1:345:3 | { ... } | calls.rb:223:5:223:5 | x | -| calls.rb:343:1:345:3 | { ... } | calls.rb:343:8:343:8 | y | -| calls.rb:343:1:345:3 | { ... } | calls.rb:343:11:343:11 | z | -| calls.rb:357:1:361:3 | ... = ... | calls.rb:1:1:367:24 | self | -| calls.rb:357:1:361:3 | ... = ... | calls.rb:343:8:343:8 | y | -| calls.rb:357:5:361:3 | -> { ... } | calls.rb:1:1:367:24 | self | -| calls.rb:357:5:361:3 | -> { ... } | calls.rb:343:8:343:8 | y | diff --git a/ruby/ql/test/library-tests/ast/control/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/ast/control/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 366b4928e753..000000000000 --- a/ruby/ql/test/library-tests/ast/control/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,15 +0,0 @@ -ambiguousReadNode -| loops.rb:9:1:12:3 | { ... } | loops.rb:2:1:2:3 | foo | -| loops.rb:9:1:12:3 | { ... } | loops.rb:3:1:3:3 | sum | -| loops.rb:9:1:12:3 | { ... } | loops.rb:9:5:9:5 | n | -| loops.rb:16:1:19:3 | { ... } | loops.rb:2:1:2:3 | foo | -| loops.rb:16:1:19:3 | { ... } | loops.rb:3:1:3:3 | sum | -| loops.rb:16:1:19:3 | { ... } | loops.rb:9:5:9:5 | n | -| loops.rb:22:1:25:3 | { ... } | loops.rb:2:1:2:3 | foo | -| loops.rb:22:1:25:3 | { ... } | loops.rb:3:1:3:3 | sum | -| loops.rb:22:1:25:3 | { ... } | loops.rb:22:5:22:7 | key | -| loops.rb:22:1:25:3 | { ... } | loops.rb:22:10:22:14 | value | -| loops.rb:28:1:32:3 | { ... } | loops.rb:2:1:2:3 | foo | -| loops.rb:28:1:32:3 | { ... } | loops.rb:3:1:3:3 | sum | -| loops.rb:28:1:32:3 | { ... } | loops.rb:22:5:22:7 | key | -| loops.rb:28:1:32:3 | { ... } | loops.rb:22:10:22:14 | value | diff --git a/ruby/ql/test/library-tests/ast/erb/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/ast/erb/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 636387e9a992..000000000000 --- a/ruby/ql/test/library-tests/ast/erb/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| template.html.erb:27:6:31:8 | { ... } | template.html.erb:25:4:25:5 | xs | -| template.html.erb:27:6:31:8 | { ... } | template.html.erb:27:10:27:10 | x | diff --git a/ruby/ql/test/library-tests/controlflow/graph/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/controlflow/graph/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 1fe0734c92df..000000000000 --- a/ruby/ql/test/library-tests/controlflow/graph/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,5 +0,0 @@ -ambiguousReadNode -| cfg.rb:90:1:93:3 | { ... } | cfg.rb:1:1:221:1 | self | -| cfg.rb:90:1:93:3 | { ... } | cfg.rb:74:1:74:1 | x | -| raise.rb:155:16:155:50 | { ... } | raise.rb:154:1:156:3 | self | -| raise.rb:155:16:155:50 | { ... } | raise.rb:154:9:154:15 | element | diff --git a/ruby/ql/test/library-tests/dataflow/array-flow/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/dataflow/array-flow/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 2af36de73337..000000000000 --- a/ruby/ql/test/library-tests/dataflow/array-flow/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| array_flow.rb:404:9:406:7 | { ... } | array_flow.rb:402:1:409:3 | self | -| array_flow.rb:404:9:406:7 | { ... } | array_flow.rb:404:13:404:13 | x | diff --git a/ruby/ql/test/library-tests/dataflow/call-sensitivity/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/dataflow/call-sensitivity/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 8861088fef5b..000000000000 --- a/ruby/ql/test/library-tests/dataflow/call-sensitivity/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| call_sensitivity.rb:75:20:77:7 | do ... end | call_sensitivity.rb:74:15:74:15 | x | -| call_sensitivity.rb:75:20:77:7 | do ... end | call_sensitivity.rb:74:18:74:18 | y | diff --git a/ruby/ql/test/library-tests/dataflow/global/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/dataflow/global/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index b454f80cd36f..000000000000 --- a/ruby/ql/test/library-tests/dataflow/global/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,85 +0,0 @@ -ambiguousReadNode -| captured_variables.rb:10:5:10:23 | ... = ... | captured_variables.rb:9:1:12:3 | self | -| captured_variables.rb:10:5:10:23 | ... = ... | captured_variables.rb:9:24:9:24 | x | -| captured_variables.rb:10:10:10:23 | -> { ... } | captured_variables.rb:9:1:12:3 | self | -| captured_variables.rb:10:10:10:23 | -> { ... } | captured_variables.rb:9:24:9:24 | x | -| captured_variables.rb:11:5:11:6 | fn | captured_variables.rb:9:1:12:3 | self | -| captured_variables.rb:11:5:11:6 | fn | captured_variables.rb:9:24:9:24 | x | -| captured_variables.rb:16:5:18:5 | -> { ... } | captured_variables.rb:15:1:19:3 | self | -| captured_variables.rb:16:5:18:5 | -> { ... } | captured_variables.rb:15:28:15:28 | x | -| captured_variables.rb:16:5:18:5 | ... | captured_variables.rb:15:1:19:3 | self | -| captured_variables.rb:16:5:18:5 | ... | captured_variables.rb:15:28:15:28 | x | -| captured_variables.rb:23:5:25:5 | -> { ... } | captured_variables.rb:22:1:26:3 | self | -| captured_variables.rb:23:5:25:5 | -> { ... } | captured_variables.rb:22:28:22:28 | x | -| captured_variables.rb:23:5:25:5 | ... | captured_variables.rb:22:1:26:3 | self | -| captured_variables.rb:23:5:25:5 | ... | captured_variables.rb:22:28:22:28 | x | -| captured_variables.rb:30:5:32:5 | ... = ... | captured_variables.rb:29:1:34:3 | self | -| captured_variables.rb:30:5:32:5 | ... = ... | captured_variables.rb:29:33:29:33 | x | -| captured_variables.rb:30:10:32:5 | -> { ... } | captured_variables.rb:29:1:34:3 | self | -| captured_variables.rb:30:10:32:5 | -> { ... } | captured_variables.rb:29:33:29:33 | x | -| captured_variables.rb:33:29:33:30 | fn | captured_variables.rb:29:1:34:3 | self | -| captured_variables.rb:33:29:33:30 | fn | captured_variables.rb:29:33:29:33 | x | -| captured_variables.rb:41:5:43:5 | ... = ... | captured_variables.rb:40:1:45:3 | self | -| captured_variables.rb:41:5:43:5 | ... = ... | captured_variables.rb:40:31:40:31 | x | -| captured_variables.rb:41:10:43:5 | -> { ... } | captured_variables.rb:40:1:45:3 | self | -| captured_variables.rb:41:10:43:5 | -> { ... } | captured_variables.rb:40:31:40:31 | x | -| captured_variables.rb:44:13:44:14 | fn | captured_variables.rb:40:1:45:3 | self | -| captured_variables.rb:44:13:44:14 | fn | captured_variables.rb:40:31:40:31 | x | -| captured_variables.rb:49:16:52:3 | do ... end | captured_variables.rb:1:1:244:2 | self | -| captured_variables.rb:49:16:52:3 | do ... end | captured_variables.rb:48:1:48:1 | x | -| captured_variables.rb:67:16:70:3 | do ... end | captured_variables.rb:1:1:244:2 | self | -| captured_variables.rb:67:16:70:3 | do ... end | captured_variables.rb:65:1:65:3 | foo | -| captured_variables.rb:78:20:80:7 | do ... end | captured_variables.rb:1:1:244:2 | self | -| captured_variables.rb:78:20:80:7 | do ... end | captured_variables.rb:65:1:65:3 | foo | -| captured_variables.rb:86:1:89:1 | ... = ... | captured_variables.rb:1:1:244:2 | self | -| captured_variables.rb:86:1:89:1 | ... = ... | captured_variables.rb:85:1:85:1 | y | -| captured_variables.rb:86:6:89:1 | -> { ... } | captured_variables.rb:1:1:244:2 | self | -| captured_variables.rb:86:6:89:1 | -> { ... } | captured_variables.rb:85:1:85:1 | y | -| captured_variables.rb:90:1:90:2 | fn | captured_variables.rb:1:1:244:2 | self | -| captured_variables.rb:90:1:90:2 | fn | captured_variables.rb:85:1:85:1 | y | -| captured_variables.rb:94:5:96:5 | -> { ... } | captured_variables.rb:93:1:97:3 | self | -| captured_variables.rb:94:5:96:5 | -> { ... } | captured_variables.rb:93:17:93:17 | x | -| captured_variables.rb:94:5:96:5 | ... | captured_variables.rb:93:1:97:3 | self | -| captured_variables.rb:94:5:96:5 | ... | captured_variables.rb:93:17:93:17 | x | -| captured_variables.rb:110:5:116:5 | ... = ... | captured_variables.rb:108:1:119:3 | self | -| captured_variables.rb:110:5:116:5 | ... = ... | captured_variables.rb:109:5:109:5 | x | -| captured_variables.rb:110:14:116:5 | -> { ... } | captured_variables.rb:108:1:119:3 | self | -| captured_variables.rb:110:14:116:5 | -> { ... } | captured_variables.rb:109:5:109:5 | x | -| captured_variables.rb:117:5:117:10 | middle | captured_variables.rb:108:1:119:3 | self | -| captured_variables.rb:117:5:117:10 | middle | captured_variables.rb:109:5:109:5 | x | -| captured_variables.rb:125:5:127:5 | ... = ... | captured_variables.rb:122:1:142:3 | self | -| captured_variables.rb:125:5:127:5 | ... = ... | captured_variables.rb:123:5:123:5 | x | -| captured_variables.rb:125:11:127:5 | -> { ... } | captured_variables.rb:122:1:142:3 | self | -| captured_variables.rb:125:11:127:5 | -> { ... } | captured_variables.rb:123:5:123:5 | x | -| captured_variables.rb:129:5:137:5 | ... = ... | captured_variables.rb:122:1:142:3 | self | -| captured_variables.rb:129:5:137:5 | ... = ... | captured_variables.rb:123:5:123:5 | x | -| captured_variables.rb:129:11:137:5 | -> { ... } | captured_variables.rb:122:1:142:3 | self | -| captured_variables.rb:129:11:137:5 | -> { ... } | captured_variables.rb:123:5:123:5 | x | -| captured_variables.rb:130:9:136:11 | ... | captured_variables.rb:129:11:137:5 | this | -| captured_variables.rb:130:9:136:11 | ... | captured_variables.rb:130:9:130:9 | y | -| captured_variables.rb:132:9:134:9 | ... = ... | captured_variables.rb:129:11:137:5 | this | -| captured_variables.rb:132:9:134:9 | ... = ... | captured_variables.rb:130:9:130:9 | y | -| captured_variables.rb:132:15:134:9 | -> { ... } | captured_variables.rb:129:11:137:5 | this | -| captured_variables.rb:132:15:134:9 | -> { ... } | captured_variables.rb:130:9:130:9 | y | -| captured_variables.rb:139:11:139:13 | fn3 | captured_variables.rb:122:1:142:3 | self | -| captured_variables.rb:139:11:139:13 | fn3 | captured_variables.rb:123:5:123:5 | x | -| captured_variables.rb:141:5:141:7 | fn1 | captured_variables.rb:122:1:142:3 | self | -| captured_variables.rb:141:5:141:7 | fn1 | captured_variables.rb:123:5:123:5 | x | -| captured_variables.rb:205:5:213:5 | ... = ... | captured_variables.rb:196:1:216:3 | self | -| captured_variables.rb:205:5:213:5 | ... = ... | captured_variables.rb:197:5:197:5 | x | -| captured_variables.rb:205:10:213:5 | -> { ... } | captured_variables.rb:196:1:216:3 | self | -| captured_variables.rb:205:10:213:5 | -> { ... } | captured_variables.rb:197:5:197:5 | x | -| captured_variables.rb:215:5:215:6 | fn | captured_variables.rb:196:1:216:3 | self | -| captured_variables.rb:215:5:215:6 | fn | captured_variables.rb:197:5:197:5 | x | -| captured_variables.rb:222:5:224:5 | ... = ... | captured_variables.rb:219:5:219:5 | x | -| captured_variables.rb:222:5:224:5 | ... = ... | captured_variables.rb:220:5:220:5 | y | -| captured_variables.rb:222:11:224:5 | -> { ... } | captured_variables.rb:219:5:219:5 | x | -| captured_variables.rb:222:11:224:5 | -> { ... } | captured_variables.rb:220:5:220:5 | y | -| captured_variables.rb:226:5:226:7 | fn1 | captured_variables.rb:219:5:219:5 | x | -| captured_variables.rb:226:5:226:7 | fn1 | captured_variables.rb:220:5:220:5 | y | -| captured_variables.rb:235:5:237:5 | ... = ... | captured_variables.rb:232:1:242:3 | self | -| captured_variables.rb:235:5:237:5 | ... = ... | captured_variables.rb:233:5:233:5 | x | -| captured_variables.rb:235:11:237:5 | -> { ... } | captured_variables.rb:232:1:242:3 | self | -| captured_variables.rb:235:11:237:5 | -> { ... } | captured_variables.rb:233:5:233:5 | x | -| captured_variables.rb:241:5:241:7 | fn1 | captured_variables.rb:232:1:242:3 | self | -| captured_variables.rb:241:5:241:7 | fn1 | captured_variables.rb:233:5:233:5 | x | diff --git a/ruby/ql/test/library-tests/dataflow/local/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/dataflow/local/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 7a65959a07bb..000000000000 --- a/ruby/ql/test/library-tests/dataflow/local/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| local_dataflow.rb:10:5:13:3 | { ... } | local_dataflow.rb:1:1:174:4 | self | -| local_dataflow.rb:10:5:13:3 | { ... } | local_dataflow.rb:10:9:10:9 | x | diff --git a/ruby/ql/test/library-tests/frameworks/action_view/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/frameworks/action_view/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index df37e38d506f..000000000000 --- a/ruby/ql/test/library-tests/frameworks/action_view/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| app/views/foo/bars/show.html.erb:10:37:12:6 | do ... end | app/views/foo/bars/show.html.erb:1:14:33:43 | self | -| app/views/foo/bars/show.html.erb:10:37:12:6 | do ... end | app/views/foo/bars/show.html.erb:6:4:6:6 | key | diff --git a/ruby/ql/test/library-tests/frameworks/rack/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/frameworks/rack/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 8fd7077be5e1..000000000000 --- a/ruby/ql/test/library-tests/frameworks/rack/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,6 +0,0 @@ -ambiguousReadNode -| rack.rb:34:32:34:69 | { ... } | rack.rb:30:3:36:5 | self | -| rack.rb:34:32:34:69 | { ... } | rack.rb:30:12:30:14 | env | -| rack.rb:34:32:34:69 | { ... } | rack.rb:31:5:31:12 | began_at | -| rack.rb:34:32:34:69 | { ... } | rack.rb:32:5:32:10 | status | -| rack.rb:34:32:34:69 | { ... } | rack.rb:32:13:32:18 | header | diff --git a/ruby/ql/test/library-tests/frameworks/sinatra/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/frameworks/sinatra/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 528b95a4a187..000000000000 --- a/ruby/ql/test/library-tests/frameworks/sinatra/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| app.rb:64:41:64:57 | { ... } | app.rb:64:21:64:59 | this | -| app.rb:64:41:64:57 | { ... } | app.rb:64:24:64:28 | value | diff --git a/ruby/ql/test/library-tests/modules/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/modules/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index fa3f6afe3fad..000000000000 --- a/ruby/ql/test/library-tests/modules/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| calls.rb:492:35:494:11 | do ... end | calls.rb:491:18:495:7 | this | -| calls.rb:492:35:494:11 | do ... end | calls.rb:491:22:491:22 | i | diff --git a/ruby/ql/test/library-tests/variables/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/library-tests/variables/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 6c2cca383f88..000000000000 --- a/ruby/ql/test/library-tests/variables/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,15 +0,0 @@ -ambiguousReadNode -| nested_scopes.rb:18:23:18:36 | { ... } | nested_scopes.rb:16:21:19:15 | this | -| nested_scopes.rb:18:23:18:36 | { ... } | nested_scopes.rb:16:29:16:29 | a | -| parameters.rb:54:9:57:3 | do ... end | parameters.rb:1:1:62:1 | self | -| parameters.rb:54:9:57:3 | do ... end | parameters.rb:53:1:53:1 | x | -| scopes.rb:9:9:18:3 | do ... end | scopes.rb:1:1:89:4 | self | -| scopes.rb:9:9:18:3 | do ... end | scopes.rb:7:1:7:1 | a | -| ssa.rb:26:3:28:5 | { ... } | ssa.rb:25:1:30:3 | self | -| ssa.rb:26:3:28:5 | { ... } | ssa.rb:26:7:26:10 | elem | -| ssa.rb:66:11:70:5 | do ... end | ssa.rb:64:1:72:3 | self | -| ssa.rb:66:11:70:5 | do ... end | ssa.rb:65:3:65:10 | captured | -| ssa.rb:76:7:78:5 | do ... end | ssa.rb:74:1:79:3 | self | -| ssa.rb:76:7:78:5 | do ... end | ssa.rb:75:3:75:10 | captured | -| ssa.rb:83:7:87:5 | do ... end | ssa.rb:81:1:88:3 | self | -| ssa.rb:83:7:87:5 | do ... end | ssa.rb:82:3:82:10 | captured | diff --git a/ruby/ql/test/query-tests/experimental/InsecureRandomness/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/experimental/InsecureRandomness/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index bc17a7c2a860..000000000000 --- a/ruby/ql/test/query-tests/experimental/InsecureRandomness/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| InsecureRandomness.rb:6:34:6:60 | { ... } | InsecureRandomness.rb:3:1:7:3 | self | -| InsecureRandomness.rb:6:34:6:60 | { ... } | InsecureRandomness.rb:4:3:4:7 | chars | diff --git a/ruby/ql/test/query-tests/experimental/improper-memoization/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/experimental/improper-memoization/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 19f2d36a5fd6..000000000000 --- a/ruby/ql/test/query-tests/experimental/improper-memoization/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,5 +0,0 @@ -ambiguousReadNode -| improper_memoization.rb:42:25:44:7 | do ... end | improper_memoization.rb:41:20:45:5 | this | -| improper_memoization.rb:42:25:44:7 | do ... end | improper_memoization.rb:41:28:41:31 | arg1 | -| improper_memoization.rb:83:21:85:5 | do ... end | improper_memoization.rb:82:1:87:3 | self | -| improper_memoization.rb:83:21:85:5 | do ... end | improper_memoization.rb:82:15:82:18 | arg2 | diff --git a/ruby/ql/test/query-tests/security/cwe-079/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/security/cwe-079/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index f595abd76408..000000000000 --- a/ruby/ql/test/query-tests/security/cwe-079/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,5 +0,0 @@ -ambiguousReadNode -| app/views/foo/bars/show.html.erb:15:4:18:6 | { ... } | app/views/foo/bars/show.html.erb:2:14:89:48 | self | -| app/views/foo/bars/show.html.erb:15:4:18:6 | { ... } | app/views/foo/bars/show.html.erb:10:4:10:6 | key | -| app/views/foo/stores/show.html.erb:12:4:15:6 | { ... } | app/views/foo/stores/show.html.erb:2:5:90:48 | self | -| app/views/foo/stores/show.html.erb:12:4:15:6 | { ... } | app/views/foo/stores/show.html.erb:7:4:7:6 | key | diff --git a/ruby/ql/test/query-tests/variables/DeadStoreOfLocal/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/variables/DeadStoreOfLocal/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index e9dd3ea8adfe..000000000000 --- a/ruby/ql/test/query-tests/variables/DeadStoreOfLocal/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,5 +0,0 @@ -ambiguousReadNode -| DeadStoreOfLocal.rb:44:14:47:7 | do ... end | DeadStoreOfLocal.rb:43:1:48:3 | self | -| DeadStoreOfLocal.rb:44:14:47:7 | do ... end | DeadStoreOfLocal.rb:43:20:43:20 | x | -| DeadStoreOfLocal.rb:57:16:65:7 | do ... end | DeadStoreOfLocal.rb:56:1:66:3 | self | -| DeadStoreOfLocal.rb:57:16:65:7 | do ... end | DeadStoreOfLocal.rb:56:17:56:17 | x | diff --git a/ruby/ql/test/query-tests/variables/UninitializedLocal/CONSISTENCY/VariablesConsistency.expected b/ruby/ql/test/query-tests/variables/UninitializedLocal/CONSISTENCY/VariablesConsistency.expected deleted file mode 100644 index 4193d87746f6..000000000000 --- a/ruby/ql/test/query-tests/variables/UninitializedLocal/CONSISTENCY/VariablesConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| UninitializedLocal.rb:73:5:75:7 | { ... } | UninitializedLocal.rb:72:1:77:3 | self | -| UninitializedLocal.rb:73:5:75:7 | { ... } | UninitializedLocal.rb:73:9:73:9 | i | diff --git a/rust/ql/test/library-tests/controlflow/CONSISTENCY/VariableCaptureConsistency.expected b/rust/ql/test/library-tests/controlflow/CONSISTENCY/VariableCaptureConsistency.expected deleted file mode 100644 index 87bc24d5e5a6..000000000000 --- a/rust/ql/test/library-tests/controlflow/CONSISTENCY/VariableCaptureConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -ambiguousReadNode -| test.rs:511:28:516:9 | { ... } | test.rs:511:22:516:9 | this | -| test.rs:511:28:516:9 | { ... } | test.rs:511:23:511:25 | foo | diff --git a/rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/VariableCaptureConsistency.expected b/rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/VariableCaptureConsistency.expected deleted file mode 100644 index b8abfaf72c0e..000000000000 --- a/rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/VariableCaptureConsistency.expected +++ /dev/null @@ -1,17 +0,0 @@ -ambiguousReadNode -| lifetime.rs:514:2:527:2 | return ... | lifetime.rs:509:16:509:17 | p3 | -| lifetime.rs:514:2:527:2 | return ... | lifetime.rs:509:32:509:33 | p4 | -| lifetime.rs:514:2:527:2 | return ... | lifetime.rs:511:6:511:14 | my_local2 | -| lifetime.rs:514:2:527:2 | return ... | lifetime.rs:512:6:512:7 | p1 | -| lifetime.rs:514:9:527:2 | \|...\| ... | lifetime.rs:509:16:509:17 | p3 | -| lifetime.rs:514:9:527:2 | \|...\| ... | lifetime.rs:509:32:509:33 | p4 | -| lifetime.rs:514:9:527:2 | \|...\| ... | lifetime.rs:511:6:511:14 | my_local2 | -| lifetime.rs:514:9:527:2 | \|...\| ... | lifetime.rs:512:6:512:7 | p1 | -| lifetime.rs:567:2:580:2 | return ... | lifetime.rs:562:22:562:23 | p3 | -| lifetime.rs:567:2:580:2 | return ... | lifetime.rs:562:38:562:39 | p4 | -| lifetime.rs:567:2:580:2 | return ... | lifetime.rs:564:6:564:14 | my_local2 | -| lifetime.rs:567:2:580:2 | return ... | lifetime.rs:565:6:565:7 | p1 | -| lifetime.rs:567:9:580:2 | { ... } | lifetime.rs:562:22:562:23 | p3 | -| lifetime.rs:567:9:580:2 | { ... } | lifetime.rs:562:38:562:39 | p4 | -| lifetime.rs:567:9:580:2 | { ... } | lifetime.rs:564:6:564:14 | my_local2 | -| lifetime.rs:567:9:580:2 | { ... } | lifetime.rs:565:6:565:7 | p1 | From 649e8ccca8d85303f6df4e56c979c073b66f4363 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 16:16:44 +0200 Subject: [PATCH 08/40] unified: Update local SSA consistency output Unified also had consistency errors from its LocalSSA instantiation, due to its use of synthetic read nodes to represent post-update positions. Many variables can have a post-update at the same CFG node. --- .../CONSISTENCY/LocalSsaConsistency.expected | 25 -- .../CONSISTENCY/LocalSsaConsistency.expected | 5 - .../CONSISTENCY/LocalSsaConsistency.expected | 5 - .../CONSISTENCY/LocalSsaConsistency.expected | 18 - .../CONSISTENCY/LocalSsaConsistency.expected | 41 --- .../CONSISTENCY/LocalSsaConsistency.expected | 347 ------------------ 6 files changed, 441 deletions(-) diff --git a/unified/ql/test/library-tests/BasicTest/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/BasicTest/CONSISTENCY/LocalSsaConsistency.expected index 32f5189788a0..e69de29bb2d1 100644 --- a/unified/ql/test/library-tests/BasicTest/CONSISTENCY/LocalSsaConsistency.expected +++ b/unified/ql/test/library-tests/BasicTest/CONSISTENCY/LocalSsaConsistency.expected @@ -1,25 +0,0 @@ -ambiguousReadNode -| test.swift:8:9:8:26 | [variable post-update] item | test.swift:7:5:9:5 | self | -| test.swift:8:9:8:26 | [variable post-update] item | test.swift:7:25:7:28 | item | -| test.swift:8:9:8:26 | [variable post-update] self | test.swift:7:5:9:5 | self | -| test.swift:8:9:8:26 | [variable post-update] self | test.swift:7:25:7:28 | item | -| test.swift:12:16:12:35 | [variable post-update] item | test.swift:11:5:13:5 | self | -| test.swift:12:16:12:35 | [variable post-update] item | test.swift:11:21:11:24 | item | -| test.swift:12:16:12:35 | [variable post-update] self | test.swift:11:5:13:5 | self | -| test.swift:12:16:12:35 | [variable post-update] self | test.swift:11:21:11:24 | item | -| test.swift:27:13:27:33 | [variable post-update] item | test.swift:25:9:25:14 | result | -| test.swift:27:13:27:33 | [variable post-update] item | test.swift:26:9:26:12 | item | -| test.swift:27:13:27:33 | [variable post-update] result | test.swift:25:9:25:14 | result | -| test.swift:27:13:27:33 | [variable post-update] result | test.swift:26:9:26:12 | item | -| test.swift:28:13:28:31 | [variable post-update] item | test.swift:25:9:25:14 | result | -| test.swift:28:13:28:31 | [variable post-update] item | test.swift:26:9:26:12 | item | -| test.swift:28:13:28:31 | [variable post-update] result | test.swift:25:9:25:14 | result | -| test.swift:28:13:28:31 | [variable post-update] result | test.swift:26:9:26:12 | item | -| test.swift:49:16:49:26 | [variable post-update] index | test.swift:47:5:50:5 | self | -| test.swift:49:16:49:26 | [variable post-update] index | test.swift:47:18:47:22 | index | -| test.swift:49:16:49:26 | [variable post-update] self | test.swift:47:5:50:5 | self | -| test.swift:49:16:49:26 | [variable post-update] self | test.swift:47:18:47:22 | index | -| test.swift:53:9:53:25 | [variable post-update] item | test.swift:52:5:54:5 | self | -| test.swift:53:9:53:25 | [variable post-update] item | test.swift:52:16:52:19 | item | -| test.swift:53:9:53:25 | [variable post-update] self | test.swift:52:5:54:5 | self | -| test.swift:53:9:53:25 | [variable post-update] self | test.swift:52:16:52:19 | item | diff --git a/unified/ql/test/library-tests/constructors/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/constructors/CONSISTENCY/LocalSsaConsistency.expected index bbb75f55a047..e69de29bb2d1 100644 --- a/unified/ql/test/library-tests/constructors/CONSISTENCY/LocalSsaConsistency.expected +++ b/unified/ql/test/library-tests/constructors/CONSISTENCY/LocalSsaConsistency.expected @@ -1,5 +0,0 @@ -ambiguousReadNode -| constructors.swift:35:9:35:29 | [variable post-update] self | constructors.swift:34:5:36:5 | self | -| constructors.swift:35:9:35:29 | [variable post-update] self | constructors.swift:34:22:34:22 | x | -| constructors.swift:35:9:35:29 | [variable post-update] x | constructors.swift:34:5:36:5 | self | -| constructors.swift:35:9:35:29 | [variable post-update] x | constructors.swift:34:22:34:22 | x | diff --git a/unified/ql/test/library-tests/dataflow/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/dataflow/CONSISTENCY/LocalSsaConsistency.expected index cc9c71d9b150..e69de29bb2d1 100644 --- a/unified/ql/test/library-tests/dataflow/CONSISTENCY/LocalSsaConsistency.expected +++ b/unified/ql/test/library-tests/dataflow/CONSISTENCY/LocalSsaConsistency.expected @@ -1,5 +0,0 @@ -ambiguousReadNode -| test.swift:184:5:184:19 | [variable post-update] x | test.swift:182:9:182:9 | x | -| test.swift:184:5:184:19 | [variable post-update] x | test.swift:183:9:183:9 | y | -| test.swift:184:5:184:19 | [variable post-update] y | test.swift:182:9:182:9 | x | -| test.swift:184:5:184:19 | [variable post-update] y | test.swift:183:9:183:9 | y | diff --git a/unified/ql/test/library-tests/mad/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/mad/CONSISTENCY/LocalSsaConsistency.expected index 6a0d83888e90..e69de29bb2d1 100644 --- a/unified/ql/test/library-tests/mad/CONSISTENCY/LocalSsaConsistency.expected +++ b/unified/ql/test/library-tests/mad/CONSISTENCY/LocalSsaConsistency.expected @@ -1,18 +0,0 @@ -ambiguousReadNode -| test.swift:74:9:84:31 | [variable post-update] encryptionKey | test.swift:67:5:67:17 | encryptionKey | -| test.swift:74:9:84:31 | [variable post-update] encryptionKey | test.swift:68:5:68:11 | fileURL | -| test.swift:74:9:84:31 | [variable post-update] fileURL | test.swift:67:5:67:17 | encryptionKey | -| test.swift:74:9:84:31 | [variable post-update] fileURL | test.swift:68:5:68:11 | fileURL | -| test.swift:86:9:96:31 | [variable post-update] encryptionKey | test.swift:67:5:67:17 | encryptionKey | -| test.swift:86:9:96:31 | [variable post-update] encryptionKey | test.swift:68:5:68:11 | fileURL | -| test.swift:86:9:96:31 | [variable post-update] fileURL | test.swift:67:5:67:17 | encryptionKey | -| test.swift:86:9:96:31 | [variable post-update] fileURL | test.swift:68:5:68:11 | fileURL | -| test.swift:98:9:109:31 | [variable post-update] encryptionKey | test.swift:67:5:67:17 | encryptionKey | -| test.swift:98:9:109:31 | [variable post-update] encryptionKey | test.swift:68:5:68:11 | fileURL | -| test.swift:98:9:109:31 | [variable post-update] encryptionKey | test.swift:69:5:69:16 | seedFilePath | -| test.swift:98:9:109:31 | [variable post-update] fileURL | test.swift:67:5:67:17 | encryptionKey | -| test.swift:98:9:109:31 | [variable post-update] fileURL | test.swift:68:5:68:11 | fileURL | -| test.swift:98:9:109:31 | [variable post-update] fileURL | test.swift:69:5:69:16 | seedFilePath | -| test.swift:98:9:109:31 | [variable post-update] seedFilePath | test.swift:67:5:67:17 | encryptionKey | -| test.swift:98:9:109:31 | [variable post-update] seedFilePath | test.swift:68:5:68:11 | fileURL | -| test.swift:98:9:109:31 | [variable post-update] seedFilePath | test.swift:69:5:69:16 | seedFilePath | diff --git a/unified/ql/test/library-tests/type-inference/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/library-tests/type-inference/CONSISTENCY/LocalSsaConsistency.expected index b48e15341459..e69de29bb2d1 100644 --- a/unified/ql/test/library-tests/type-inference/CONSISTENCY/LocalSsaConsistency.expected +++ b/unified/ql/test/library-tests/type-inference/CONSISTENCY/LocalSsaConsistency.expected @@ -1,41 +0,0 @@ -ambiguousReadNode -| closures.swift:47:9:47:21 | [variable post-update] self | closures.swift:45:5:49:5 | self | -| closures.swift:47:9:47:21 | [variable post-update] self | closures.swift:45:24:45:28 | value | -| closures.swift:47:9:47:21 | [variable post-update] value | closures.swift:45:5:49:5 | self | -| closures.swift:47:9:47:21 | [variable post-update] value | closures.swift:45:24:45:28 | value | -| closures.swift:48:16:48:29 | [variable post-update] self | closures.swift:45:5:49:5 | self | -| closures.swift:48:16:48:29 | [variable post-update] self | closures.swift:45:24:45:28 | value | -| closures.swift:48:16:48:29 | [variable post-update] value | closures.swift:45:5:49:5 | self | -| closures.swift:48:16:48:29 | [variable post-update] value | closures.swift:45:24:45:28 | value | -| generics.swift:156:5:156:22 | [variable post-update] v1 | generics.swift:155:10:155:11 | v1 | -| generics.swift:156:5:156:22 | [variable post-update] v1 | generics.swift:155:20:155:21 | v2 | -| generics.swift:156:5:156:22 | [variable post-update] v2 | generics.swift:155:10:155:11 | v1 | -| generics.swift:156:5:156:22 | [variable post-update] v2 | generics.swift:155:20:155:21 | v2 | -| key_paths.swift:44:14:44:35 | [variable post-update] e | key_paths.swift:42:7:42:7 | s | -| key_paths.swift:44:14:44:35 | [variable post-update] e | key_paths.swift:43:7:43:7 | e | -| key_paths.swift:44:14:44:35 | [variable post-update] s | key_paths.swift:42:7:42:7 | s | -| key_paths.swift:44:14:44:35 | [variable post-update] s | key_paths.swift:43:7:43:7 | e | -| key_paths.swift:142:18:142:45 | [variable post-update] kpStart | key_paths.swift:140:7:140:13 | kpStart | -| key_paths.swift:142:18:142:45 | [variable post-update] kpStart | key_paths.swift:141:7:141:9 | kpX | -| key_paths.swift:142:18:142:45 | [variable post-update] kpX | key_paths.swift:140:7:140:13 | kpStart | -| key_paths.swift:142:18:142:45 | [variable post-update] kpX | key_paths.swift:141:7:141:9 | kpX | -| key_paths.swift:146:14:146:35 | [variable post-update] e | key_paths.swift:144:7:144:7 | s | -| key_paths.swift:146:14:146:35 | [variable post-update] e | key_paths.swift:145:7:145:7 | e | -| key_paths.swift:146:14:146:35 | [variable post-update] s | key_paths.swift:144:7:144:7 | s | -| key_paths.swift:146:14:146:35 | [variable post-update] s | key_paths.swift:145:7:145:7 | e | -| overload_resolution.swift:371:5:371:34 | [variable post-update] name | overload_resolution.swift:370:3:372:3 | self | -| overload_resolution.swift:371:5:371:34 | [variable post-update] name | overload_resolution.swift:370:20:370:23 | name | -| overload_resolution.swift:371:5:371:34 | [variable post-update] self | overload_resolution.swift:370:3:372:3 | self | -| overload_resolution.swift:371:5:371:34 | [variable post-update] self | overload_resolution.swift:370:20:370:23 | name | -| overload_resolution.swift:375:5:375:42 | [variable post-update] self | overload_resolution.swift:374:3:376:3 | self | -| overload_resolution.swift:375:5:375:42 | [variable post-update] self | overload_resolution.swift:374:20:374:23 | size | -| overload_resolution.swift:375:5:375:42 | [variable post-update] size | overload_resolution.swift:374:3:376:3 | self | -| overload_resolution.swift:375:5:375:42 | [variable post-update] size | overload_resolution.swift:374:20:374:23 | size | -| overload_resolution.swift:415:12:415:22 | [variable post-update] index | overload_resolution.swift:414:3:416:3 | self | -| overload_resolution.swift:415:12:415:22 | [variable post-update] index | overload_resolution.swift:414:14:414:18 | index | -| overload_resolution.swift:415:12:415:22 | [variable post-update] self | overload_resolution.swift:414:3:416:3 | self | -| overload_resolution.swift:415:12:415:22 | [variable post-update] self | overload_resolution.swift:414:14:414:18 | index | -| overload_resolution.swift:419:12:419:20 | [variable post-update] key | overload_resolution.swift:418:3:420:3 | self | -| overload_resolution.swift:419:12:419:20 | [variable post-update] key | overload_resolution.swift:418:14:418:16 | key | -| overload_resolution.swift:419:12:419:20 | [variable post-update] self | overload_resolution.swift:418:3:420:3 | self | -| overload_resolution.swift:419:12:419:20 | [variable post-update] self | overload_resolution.swift:418:14:418:16 | key | diff --git a/unified/ql/test/query-tests/security/CWE-022/PathInjection/CONSISTENCY/LocalSsaConsistency.expected b/unified/ql/test/query-tests/security/CWE-022/PathInjection/CONSISTENCY/LocalSsaConsistency.expected index 173907e3ef5a..e69de29bb2d1 100644 --- a/unified/ql/test/query-tests/security/CWE-022/PathInjection/CONSISTENCY/LocalSsaConsistency.expected +++ b/unified/ql/test/query-tests/security/CWE-022/PathInjection/CONSISTENCY/LocalSsaConsistency.expected @@ -1,347 +0,0 @@ -ambiguousReadNode -| testPathInjection.swift:43:9:43:23 | [variable post-update] data | testPathInjection.swift:41:5:44:5 | self | -| testPathInjection.swift:43:9:43:23 | [variable post-update] data | testPathInjection.swift:42:13:42:16 | data | -| testPathInjection.swift:43:9:43:23 | [variable post-update] self | testPathInjection.swift:41:5:44:5 | self | -| testPathInjection.swift:43:9:43:23 | [variable post-update] self | testPathInjection.swift:42:13:42:16 | data | -| testPathInjection.swift:244:9:244:49 | [variable post-update] ascending | testPathInjection.swift:243:5:245:5 | self | -| testPathInjection.swift:244:9:244:49 | [variable post-update] ascending | testPathInjection.swift:243:66:243:74 | ascending | -| testPathInjection.swift:244:9:244:49 | [variable post-update] self | testPathInjection.swift:243:5:245:5 | self | -| testPathInjection.swift:244:9:244:49 | [variable post-update] self | testPathInjection.swift:243:66:243:74 | ascending | -| testPathInjection.swift:349:13:349:58 | [variable post-update] nsData | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:349:13:349:58 | [variable post-update] nsData | testPathInjection.swift:348:9:348:14 | nsData | -| testPathInjection.swift:349:13:349:58 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:349:13:349:58 | [variable post-update] remoteUrl | testPathInjection.swift:348:9:348:14 | nsData | -| testPathInjection.swift:350:5:350:44 | [variable post-update] nsData | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:350:5:350:44 | [variable post-update] nsData | testPathInjection.swift:348:9:348:14 | nsData | -| testPathInjection.swift:350:5:350:44 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:350:5:350:44 | [variable post-update] remoteUrl | testPathInjection.swift:348:9:348:14 | nsData | -| testPathInjection.swift:351:13:351:65 | [variable post-update] nsData | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:351:13:351:65 | [variable post-update] nsData | testPathInjection.swift:348:9:348:14 | nsData | -| testPathInjection.swift:351:13:351:65 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:351:13:351:65 | [variable post-update] remoteString | testPathInjection.swift:348:9:348:14 | nsData | -| testPathInjection.swift:352:5:352:51 | [variable post-update] nsData | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:352:5:352:51 | [variable post-update] nsData | testPathInjection.swift:348:9:348:14 | nsData | -| testPathInjection.swift:352:5:352:51 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:352:5:352:51 | [variable post-update] remoteString | testPathInjection.swift:348:9:348:14 | nsData | -| testPathInjection.swift:355:13:355:94 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:355:13:355:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:355:13:355:94 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:355:13:355:94 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:356:13:356:56 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:356:13:356:56 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:356:13:356:56 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:356:13:356:56 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:357:13:358:86 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:357:13:358:86 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:357:13:358:86 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:357:13:358:86 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:359:13:359:47 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:359:13:359:47 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:359:13:359:47 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:359:13:359:47 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:360:13:360:56 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:360:13:360:56 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:360:13:360:56 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:360:13:360:56 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:361:13:361:45 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:361:13:361:45 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:361:13:361:45 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:361:13:361:45 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:362:5:362:90 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:362:5:362:90 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:362:5:362:90 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:362:5:362:90 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:363:13:363:69 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:363:13:363:69 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:363:13:363:69 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:363:13:363:69 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:364:13:364:79 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:364:13:364:79 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:364:13:364:79 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:364:13:364:79 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:365:5:365:32 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:365:5:365:32 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:365:5:365:32 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:365:5:365:32 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:366:5:366:39 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:366:5:366:39 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:366:5:366:39 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:366:5:366:39 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:367:5:367:94 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:367:5:367:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:367:5:367:94 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:367:5:367:94 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:368:13:368:94 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:368:13:368:94 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:368:13:368:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:368:13:368:94 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:368:13:368:94 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:368:13:368:94 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:368:13:368:94 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:368:13:368:94 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:368:13:368:94 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:369:13:369:94 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:369:13:369:94 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:369:13:369:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:369:13:369:94 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:369:13:369:94 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:369:13:369:94 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:369:13:369:94 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:369:13:369:94 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:369:13:369:94 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:370:5:372:70 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:370:5:372:70 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:370:5:372:70 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:370:5:372:70 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:370:5:372:70 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:370:5:372:70 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:370:5:372:70 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:370:5:372:70 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:370:5:372:70 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:373:5:375:70 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:373:5:375:70 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:373:5:375:70 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:373:5:375:70 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:373:5:375:70 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:373:5:375:70 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:373:5:375:70 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:373:5:375:70 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:373:5:375:70 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:376:5:376:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:376:5:376:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:376:5:376:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:376:5:376:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:376:5:376:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:376:5:376:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:376:5:376:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:376:5:376:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:376:5:376:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:377:5:377:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:377:5:377:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:377:5:377:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:377:5:377:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:377:5:377:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:377:5:377:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:377:5:377:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:377:5:377:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:377:5:377:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:378:5:378:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:378:5:378:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:378:5:378:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:378:5:378:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:379:5:379:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:379:5:379:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:379:5:379:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:379:5:379:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:380:5:380:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:380:5:380:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:380:5:380:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:380:5:380:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:380:5:380:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:380:5:380:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:380:5:380:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:380:5:380:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:380:5:380:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:381:5:381:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:381:5:381:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:381:5:381:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:381:5:381:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:381:5:381:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:381:5:381:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:381:5:381:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:381:5:381:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:381:5:381:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:382:5:382:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:382:5:382:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:382:5:382:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:382:5:382:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:383:5:383:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:383:5:383:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:383:5:383:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:383:5:383:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:384:5:384:69 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:384:5:384:69 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:384:5:384:69 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:384:5:384:69 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:384:5:384:69 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:384:5:384:69 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:384:5:384:69 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:384:5:384:69 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:384:5:384:69 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:385:5:385:69 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:385:5:385:69 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:385:5:385:69 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:385:5:385:69 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:385:5:385:69 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:385:5:385:69 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:385:5:385:69 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:385:5:385:69 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:385:5:385:69 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:386:5:386:72 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:386:5:386:72 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:386:5:386:72 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:386:5:386:72 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:387:5:387:72 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:387:5:387:72 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:387:5:387:72 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:387:5:387:72 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:388:5:388:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:388:5:388:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:388:5:388:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:388:5:388:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:388:5:388:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:388:5:388:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:388:5:388:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:388:5:388:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:388:5:388:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:389:5:389:43 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:389:5:389:43 | [variable post-update] fm | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:389:5:389:43 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:389:5:389:43 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:389:5:389:43 | [variable post-update] remoteUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:389:5:389:43 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:389:5:389:43 | [variable post-update] safeUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:389:5:389:43 | [variable post-update] safeUrl | testPathInjection.swift:343:9:343:15 | safeUrl | -| testPathInjection.swift:389:5:389:43 | [variable post-update] safeUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:390:5:390:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:390:5:390:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:390:5:390:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:390:5:390:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:391:5:391:49 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:391:5:391:49 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:391:5:391:49 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:391:5:391:49 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:392:13:392:62 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:392:13:392:62 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:392:13:392:62 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:392:13:392:62 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:393:13:393:47 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:393:13:393:47 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:393:13:393:47 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:393:13:393:47 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:394:13:395:94 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:394:13:395:94 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:394:13:395:94 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:394:13:395:94 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:396:5:396:53 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:396:5:396:53 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:396:5:396:53 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:396:5:396:53 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:397:13:397:45 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:397:13:397:45 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:397:13:397:45 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:397:13:397:45 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:398:13:398:63 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:398:13:398:63 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:398:13:398:63 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:398:13:398:63 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:399:13:399:63 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:399:13:399:63 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:399:13:399:63 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:399:13:399:63 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:400:13:400:55 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:400:13:400:55 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:400:13:400:55 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:400:13:400:55 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:401:13:401:85 | [variable post-update] fm | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:401:13:401:85 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:401:13:401:85 | [variable post-update] remoteUrl | testPathInjection.swift:341:9:341:17 | remoteUrl | -| testPathInjection.swift:401:13:401:85 | [variable post-update] remoteUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:403:13:403:62 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:403:13:403:62 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:403:13:403:62 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:403:13:403:62 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:404:13:404:54 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:404:13:404:54 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:404:13:404:54 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:404:13:404:54 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:405:13:405:69 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:405:13:405:69 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:405:13:405:69 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:405:13:405:69 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:406:13:406:72 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:406:13:406:72 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:406:13:406:72 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:406:13:406:72 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:407:13:407:72 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:407:13:407:72 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:407:13:407:72 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:407:13:407:72 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:408:13:408:62 | [variable post-update] fm | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:408:13:408:62 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:408:13:408:62 | [variable post-update] remoteString | testPathInjection.swift:340:9:340:20 | remoteString | -| testPathInjection.swift:408:13:408:62 | [variable post-update] remoteString | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:409:13:410:97 | [variable post-update] fm | testPathInjection.swift:342:9:342:19 | remoteNsUrl | -| testPathInjection.swift:409:13:410:97 | [variable post-update] fm | testPathInjection.swift:344:9:344:17 | safeNsUrl | -| testPathInjection.swift:409:13:410:97 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:409:13:410:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:342:9:342:19 | remoteNsUrl | -| testPathInjection.swift:409:13:410:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:344:9:344:17 | safeNsUrl | -| testPathInjection.swift:409:13:410:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:409:13:410:97 | [variable post-update] safeNsUrl | testPathInjection.swift:342:9:342:19 | remoteNsUrl | -| testPathInjection.swift:409:13:410:97 | [variable post-update] safeNsUrl | testPathInjection.swift:344:9:344:17 | safeNsUrl | -| testPathInjection.swift:409:13:410:97 | [variable post-update] safeNsUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:411:13:412:97 | [variable post-update] fm | testPathInjection.swift:342:9:342:19 | remoteNsUrl | -| testPathInjection.swift:411:13:412:97 | [variable post-update] fm | testPathInjection.swift:344:9:344:17 | safeNsUrl | -| testPathInjection.swift:411:13:412:97 | [variable post-update] fm | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:411:13:412:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:342:9:342:19 | remoteNsUrl | -| testPathInjection.swift:411:13:412:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:344:9:344:17 | safeNsUrl | -| testPathInjection.swift:411:13:412:97 | [variable post-update] remoteNsUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:411:13:412:97 | [variable post-update] safeNsUrl | testPathInjection.swift:342:9:342:19 | remoteNsUrl | -| testPathInjection.swift:411:13:412:97 | [variable post-update] safeNsUrl | testPathInjection.swift:344:9:344:17 | safeNsUrl | -| testPathInjection.swift:411:13:412:97 | [variable post-update] safeNsUrl | testPathInjection.swift:354:9:354:10 | fm | -| testPathInjection.swift:478:5:478:60 | [variable post-update] buffer1 | testPathInjection.swift:339:11:339:17 | buffer1 | -| testPathInjection.swift:478:5:478:60 | [variable post-update] buffer1 | testPathInjection.swift:476:9:476:17 | localData | -| testPathInjection.swift:478:5:478:60 | [variable post-update] localData | testPathInjection.swift:339:11:339:17 | buffer1 | -| testPathInjection.swift:478:5:478:60 | [variable post-update] localData | testPathInjection.swift:339:11:339:17 | buffer1 | -| testPathInjection.swift:478:5:478:60 | [variable post-update] localData | testPathInjection.swift:476:9:476:17 | localData | -| testPathInjection.swift:478:5:478:60 | [variable post-update] localData | testPathInjection.swift:476:9:476:17 | localData | -| testPathInjection.swift:479:5:479:62 | [variable post-update] buffer2 | testPathInjection.swift:339:49:339:55 | buffer2 | -| testPathInjection.swift:479:5:479:62 | [variable post-update] buffer2 | testPathInjection.swift:477:9:477:18 | remoteData | -| testPathInjection.swift:479:5:479:62 | [variable post-update] remoteData | testPathInjection.swift:339:49:339:55 | buffer2 | -| testPathInjection.swift:479:5:479:62 | [variable post-update] remoteData | testPathInjection.swift:339:49:339:55 | buffer2 | -| testPathInjection.swift:479:5:479:62 | [variable post-update] remoteData | testPathInjection.swift:477:9:477:18 | remoteData | -| testPathInjection.swift:479:5:479:62 | [variable post-update] remoteData | testPathInjection.swift:477:9:477:18 | remoteData | -| testPathInjection.swift:510:17:510:49 | [variable post-update] fm | testPathInjection.swift:504:9:504:20 | remoteString | -| testPathInjection.swift:510:17:510:49 | [variable post-update] fm | testPathInjection.swift:506:9:506:10 | fm | -| testPathInjection.swift:510:17:510:49 | [variable post-update] remoteString | testPathInjection.swift:504:9:504:20 | remoteString | -| testPathInjection.swift:510:17:510:49 | [variable post-update] remoteString | testPathInjection.swift:506:9:506:10 | fm | -| testPathInjection.swift:512:13:512:45 | [variable post-update] fm | testPathInjection.swift:504:9:504:20 | remoteString | -| testPathInjection.swift:512:13:512:45 | [variable post-update] fm | testPathInjection.swift:506:9:506:10 | fm | -| testPathInjection.swift:512:13:512:45 | [variable post-update] remoteString | testPathInjection.swift:504:9:504:20 | remoteString | -| testPathInjection.swift:512:13:512:45 | [variable post-update] remoteString | testPathInjection.swift:506:9:506:10 | fm | -| testPathInjection.swift:524:28:524:66 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:524:28:524:66 | [variable post-update] remoteString | testPathInjection.swift:521:9:521:10 | u1 | -| testPathInjection.swift:524:28:524:66 | [variable post-update] u1 | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:524:28:524:66 | [variable post-update] u1 | testPathInjection.swift:521:9:521:10 | u1 | -| testPathInjection.swift:525:28:525:66 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:525:28:525:66 | [variable post-update] remoteString | testPathInjection.swift:521:9:521:10 | u1 | -| testPathInjection.swift:525:28:525:66 | [variable post-update] u1 | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:525:28:525:66 | [variable post-update] u1 | testPathInjection.swift:521:9:521:10 | u1 | -| testPathInjection.swift:526:5:526:40 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:526:5:526:40 | [variable post-update] remoteString | testPathInjection.swift:521:9:521:10 | u1 | -| testPathInjection.swift:526:5:526:40 | [variable post-update] u1 | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:526:5:526:40 | [variable post-update] u1 | testPathInjection.swift:521:9:521:10 | u1 | -| testPathInjection.swift:535:24:535:62 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:535:24:535:62 | [variable post-update] remoteString | testPathInjection.swift:532:9:532:10 | u3 | -| testPathInjection.swift:535:24:535:62 | [variable post-update] u3 | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:535:24:535:62 | [variable post-update] u3 | testPathInjection.swift:532:9:532:10 | u3 | -| testPathInjection.swift:554:9:555:75 | [variable post-update] remoteString | testPathInjection.swift:517:5:517:6 | s3 | -| testPathInjection.swift:554:9:555:75 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:554:9:555:75 | [variable post-update] s3 | testPathInjection.swift:517:5:517:6 | s3 | -| testPathInjection.swift:554:9:555:75 | [variable post-update] s3 | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:559:9:559:67 | [variable post-update] fm | testPathInjection.swift:517:39:517:40 | fm | -| testPathInjection.swift:559:9:559:67 | [variable post-update] fm | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:559:9:559:67 | [variable post-update] remoteString | testPathInjection.swift:517:39:517:40 | fm | -| testPathInjection.swift:559:9:559:67 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:560:13:560:53 | [variable post-update] fm | testPathInjection.swift:517:39:517:40 | fm | -| testPathInjection.swift:560:13:560:53 | [variable post-update] fm | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:560:13:560:53 | [variable post-update] remoteString | testPathInjection.swift:517:39:517:40 | fm | -| testPathInjection.swift:560:13:560:53 | [variable post-update] remoteString | testPathInjection.swift:519:9:519:20 | remoteString | -| testPathInjection.swift:587:5:587:41 | [variable post-update] mc | testPathInjection.swift:580:9:580:20 | remoteString | -| testPathInjection.swift:587:5:587:41 | [variable post-update] mc | testPathInjection.swift:586:9:586:10 | mc | -| testPathInjection.swift:587:5:587:41 | [variable post-update] remoteString | testPathInjection.swift:580:9:580:20 | remoteString | -| testPathInjection.swift:587:5:587:41 | [variable post-update] remoteString | testPathInjection.swift:586:9:586:10 | mc | -| testPathInjection.swift:588:5:588:34 | [variable post-update] mc | testPathInjection.swift:580:9:580:20 | remoteString | -| testPathInjection.swift:588:5:588:34 | [variable post-update] mc | testPathInjection.swift:586:9:586:10 | mc | -| testPathInjection.swift:588:5:588:34 | [variable post-update] remoteString | testPathInjection.swift:580:9:580:20 | remoteString | -| testPathInjection.swift:588:5:588:34 | [variable post-update] remoteString | testPathInjection.swift:586:9:586:10 | mc | From 0164aff6a85e21897d324408721905650f005287 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 12:48:03 +0200 Subject: [PATCH 09/40] unified: Update unit test output --- unified/ql/test/library-tests/dataflow/test.expected | 4 ---- unified/ql/test/library-tests/dataflow/test.swift | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/unified/ql/test/library-tests/dataflow/test.expected b/unified/ql/test/library-tests/dataflow/test.expected index 9ec3c9eb2890..478e0e3edfa3 100644 --- a/unified/ql/test/library-tests/dataflow/test.expected +++ b/unified/ql/test/library-tests/dataflow/test.expected @@ -179,9 +179,7 @@ edges | test.swift:175:42:175:66 | ... + ... | test.swift:175:14:175:67 | TupleExpr [1] | provenance | | | test.swift:175:52:175:66 | source(...) | test.swift:175:42:175:66 | ... + ... | provenance | | | test.swift:182:9:182:9 | x | test.swift:185:10:185:10 | x | provenance | | -| test.swift:182:9:182:9 | x | test.swift:186:10:186:10 | y | provenance | | | test.swift:182:13:182:27 | source(...) | test.swift:182:9:182:9 | x | provenance | | -| test.swift:183:9:183:9 | y | test.swift:185:10:185:10 | x | provenance | | | test.swift:183:9:183:9 | y | test.swift:186:10:186:10 | y | provenance | | | test.swift:183:13:183:27 | source(...) | test.swift:183:9:183:9 | y | provenance | | nodes @@ -489,6 +487,4 @@ testFailures | test.swift:176:10:176:10 | a | test.swift:175:25:175:39 | source(...) | test.swift:176:10:176:10 | a | $@ | test.swift:175:25:175:39 | source(...) | source(...) | | test.swift:177:10:177:10 | b | test.swift:175:52:175:66 | source(...) | test.swift:177:10:177:10 | b | $@ | test.swift:175:52:175:66 | source(...) | source(...) | | test.swift:185:10:185:10 | x | test.swift:182:13:182:27 | source(...) | test.swift:185:10:185:10 | x | $@ | test.swift:182:13:182:27 | source(...) | source(...) | -| test.swift:185:10:185:10 | x | test.swift:183:13:183:27 | source(...) | test.swift:185:10:185:10 | x | $@ | test.swift:183:13:183:27 | source(...) | source(...) | -| test.swift:186:10:186:10 | y | test.swift:182:13:182:27 | source(...) | test.swift:186:10:186:10 | y | $@ | test.swift:182:13:182:27 | source(...) | source(...) | | test.swift:186:10:186:10 | y | test.swift:183:13:183:27 | source(...) | test.swift:186:10:186:10 | y | $@ | test.swift:183:13:183:27 | source(...) | source(...) | diff --git a/unified/ql/test/library-tests/dataflow/test.swift b/unified/ql/test/library-tests/dataflow/test.swift index 36c3babdf8de..b817497a1e57 100644 --- a/unified/ql/test/library-tests/dataflow/test.swift +++ b/unified/ql/test/library-tests/dataflow/test.swift @@ -182,6 +182,6 @@ func t20() { var x = source("t20.1") var y = source("t20.2") foo(x: x, y: y) - sink(x) // $ hasValueFlow=t20.1 SPURIOUS: hasValueFlow=t20.2 - sink(y) // $ hasValueFlow=t20.2 SPURIOUS: hasValueFlow=t20.1 + sink(x) // $ hasValueFlow=t20.1 + sink(y) // $ hasValueFlow=t20.2 } From ee7fc863fd60984eba2d6d8cb8399569786afa98 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 2 Oct 2026 16:45:55 +0200 Subject: [PATCH 10/40] unified: Update path-injection output Many tests passed for the wrong reasons, due to the SSA bug. We need more library/operator modelling to actually find these flows. --- .../PathInjection/PathInjectionTest.expected | 114 ------------------ .../PathInjection/testPathInjection.swift | 46 +++---- 2 files changed, 23 insertions(+), 137 deletions(-) diff --git a/unified/ql/test/query-tests/security/CWE-022/PathInjection/PathInjectionTest.expected b/unified/ql/test/query-tests/security/CWE-022/PathInjection/PathInjectionTest.expected index 3e90894e5b86..90cd69557490 100644 --- a/unified/ql/test/query-tests/security/CWE-022/PathInjection/PathInjectionTest.expected +++ b/unified/ql/test/query-tests/security/CWE-022/PathInjection/PathInjectionTest.expected @@ -5,41 +5,15 @@ | testPathInjection.swift:359:35:359:46 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:359:35:359:46 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:360:44:360:55 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:360:44:360:55 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:361:33:361:44 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:361:33:361:44 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:362:28:362:36 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:362:28:362:36 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:363:40:363:51 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:363:40:363:51 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:364:35:364:46 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:364:35:364:46 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:365:23:365:31 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:365:23:365:31 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:366:27:366:38 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:366:27:366:38 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:367:22:367:30 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:367:22:367:30 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:368:30:368:38 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:368:30:368:38 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:369:30:369:36 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:369:30:369:36 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:369:51:369:59 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:369:51:369:59 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:371:13:371:21 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:371:13:371:21 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:371:36:371:42 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:371:36:371:42 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:374:13:374:19 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:374:13:374:19 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:374:34:374:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:374:34:374:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:376:21:376:29 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:376:21:376:29 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:376:36:376:42 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:376:36:376:42 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:377:21:377:27 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:377:21:377:27 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:377:34:377:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:377:34:377:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:378:25:378:36 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:378:25:378:36 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:379:37:379:48 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:379:37:379:48 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:380:21:380:29 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:380:21:380:29 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:380:36:380:42 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:380:36:380:42 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:381:21:381:27 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:381:21:381:27 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:381:34:381:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:381:34:381:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:382:25:382:36 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:382:25:382:36 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:383:37:383:48 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:383:37:383:48 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:384:31:384:39 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:384:31:384:39 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:384:62:384:68 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:384:62:384:68 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:385:31:385:37 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:385:31:385:37 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:385:60:385:68 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:385:60:385:68 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:386:35:386:46 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:386:35:386:46 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:387:60:387:71 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:387:60:387:71 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:388:21:388:29 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:388:21:388:29 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:388:36:388:42 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:388:36:388:42 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:389:21:389:27 | safeUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:389:21:389:27 | safeUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:389:34:389:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:389:34:389:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:390:25:390:36 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:390:25:390:36 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:391:37:391:48 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:391:37:391:48 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:392:50:392:61 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:392:50:392:61 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | @@ -50,24 +24,19 @@ | testPathInjection.swift:398:38:398:49 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:398:38:398:49 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:399:51:399:62 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:399:51:399:62 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:400:43:400:54 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:400:43:400:54 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:401:34:401:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:401:34:401:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:403:50:403:61 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:403:50:403:61 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:404:42:404:53 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:404:42:404:53 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:405:40:405:51 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:405:40:405:51 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:406:43:406:54 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:406:43:406:54 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:407:60:407:71 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:407:60:407:71 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:408:50:408:61 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:408:50:408:61 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:412:26:412:34 | safeNsUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:412:26:412:34 | safeNsUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:412:52:412:62 | remoteNsUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:412:52:412:62 | remoteNsUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:415:41:415:52 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:415:41:415:52 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:416:41:416:52 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:416:41:416:52 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:417:41:417:52 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:417:41:417:52 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:419:43:419:54 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:419:43:419:54 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:420:43:420:54 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:420:43:420:54 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:421:26:421:34 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:421:26:421:34 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:422:30:422:41 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:422:30:422:41 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:424:59:424:70 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:424:59:424:70 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:436:25:436:33 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:436:25:436:33 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:437:26:437:37 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:437:26:437:37 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:441:28:441:39 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:441:28:441:39 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:443:32:443:43 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:443:32:443:43 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | @@ -75,13 +44,10 @@ | testPathInjection.swift:447:40:447:51 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:447:40:447:51 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:456:15:456:26 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:456:15:456:26 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:482:22:482:33 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:482:22:482:33 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | -| testPathInjection.swift:484:24:484:30 | buffer2 | testPathInjection.swift:477:22:477:87 | Data(...) | testPathInjection.swift:484:24:484:30 | buffer2 | This path depends on a $@. | testPathInjection.swift:477:22:477:87 | Data(...) | user-provided value | | testPathInjection.swift:486:25:486:36 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:486:25:486:36 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:498:49:498:60 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:498:49:498:60 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:510:37:510:48 | remoteString | testPathInjection.swift:504:24:504:78 | String(...) | testPathInjection.swift:510:37:510:48 | remoteString | This path depends on a $@. | testPathInjection.swift:504:24:504:78 | String(...) | user-provided value | | testPathInjection.swift:512:33:512:44 | remoteString | testPathInjection.swift:504:24:504:78 | String(...) | testPathInjection.swift:512:33:512:44 | remoteString | This path depends on a $@. | testPathInjection.swift:504:24:504:78 | String(...) | user-provided value | -| testPathInjection.swift:525:28:525:93 | ... .appendingPathComponent(...) | testPathInjection.swift:519:24:519:78 | String(...) | testPathInjection.swift:525:28:525:93 | ... .appendingPathComponent(...) | This path depends on a $@. | testPathInjection.swift:519:24:519:78 | String(...) | user-provided value | -| testPathInjection.swift:527:28:527:29 | u1 | testPathInjection.swift:519:24:519:78 | String(...) | testPathInjection.swift:527:28:527:29 | u1 | This path depends on a $@. | testPathInjection.swift:519:24:519:78 | String(...) | user-provided value | | testPathInjection.swift:529:28:529:39 | remoteString | testPathInjection.swift:519:24:519:78 | String(...) | testPathInjection.swift:529:28:529:39 | remoteString | This path depends on a $@. | testPathInjection.swift:519:24:519:78 | String(...) | user-provided value | | testPathInjection.swift:541:32:541:43 | remoteString | testPathInjection.swift:519:24:519:78 | String(...) | testPathInjection.swift:541:32:541:43 | remoteString | This path depends on a $@. | testPathInjection.swift:519:24:519:78 | String(...) | user-provided value | | testPathInjection.swift:542:38:542:49 | remoteString | testPathInjection.swift:519:24:519:78 | String(...) | testPathInjection.swift:542:38:542:49 | remoteString | This path depends on a $@. | testPathInjection.swift:519:24:519:78 | String(...) | user-provided value | @@ -100,41 +66,15 @@ edges | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:359:35:359:46 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:360:44:360:55 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:361:33:361:44 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:362:28:362:36 | remoteUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:363:40:363:51 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:364:35:364:46 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:365:23:365:31 | remoteUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:366:27:366:38 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:367:22:367:30 | remoteUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:368:30:368:38 | remoteUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:369:30:369:36 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:369:51:369:59 | remoteUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:371:13:371:21 | remoteUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:371:36:371:42 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:374:13:374:19 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:374:34:374:42 | remoteUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:376:21:376:29 | remoteUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:376:36:376:42 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:377:21:377:27 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:377:34:377:42 | remoteUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:378:25:378:36 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:379:37:379:48 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:380:21:380:29 | remoteUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:380:36:380:42 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:381:21:381:27 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:381:34:381:42 | remoteUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:382:25:382:36 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:383:37:383:48 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:384:31:384:39 | remoteUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:384:62:384:68 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:385:31:385:37 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:385:60:385:68 | remoteUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:386:35:386:46 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:387:60:387:71 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:388:21:388:29 | remoteUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:388:36:388:42 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:389:21:389:27 | safeUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:389:34:389:42 | remoteUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:390:25:390:36 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:391:37:391:48 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:392:50:392:61 | remoteString | provenance | | @@ -145,24 +85,19 @@ edges | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:398:38:398:49 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:399:51:399:62 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:400:43:400:54 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:401:34:401:42 | remoteUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:403:50:403:61 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:404:42:404:53 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:405:40:405:51 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:406:43:406:54 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:407:60:407:71 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:408:50:408:61 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:412:26:412:34 | safeNsUrl | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:412:52:412:62 | remoteNsUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:415:41:415:52 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:416:41:416:52 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:417:41:417:52 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:419:43:419:54 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:420:43:420:54 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:421:26:421:34 | remoteUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:422:30:422:41 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:424:59:424:70 | remoteString | provenance | | -| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:436:25:436:33 | remoteUrl | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:437:26:437:37 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:441:28:441:39 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:443:32:443:43 | remoteString | provenance | | @@ -173,13 +108,9 @@ edges | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:486:25:486:36 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:498:49:498:60 | remoteString | provenance | | | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:340:9:340:20 | remoteString | provenance | | -| testPathInjection.swift:477:9:477:18 | remoteData | testPathInjection.swift:484:24:484:30 | buffer2 | provenance | | -| testPathInjection.swift:477:22:477:87 | Data(...) | testPathInjection.swift:477:9:477:18 | remoteData | provenance | | | testPathInjection.swift:504:9:504:20 | remoteString | testPathInjection.swift:510:37:510:48 | remoteString | provenance | | | testPathInjection.swift:504:9:504:20 | remoteString | testPathInjection.swift:512:33:512:44 | remoteString | provenance | | | testPathInjection.swift:504:24:504:78 | String(...) | testPathInjection.swift:504:9:504:20 | remoteString | provenance | | -| testPathInjection.swift:519:9:519:20 | remoteString | testPathInjection.swift:525:28:525:29 | u1 | provenance | | -| testPathInjection.swift:519:9:519:20 | remoteString | testPathInjection.swift:527:28:527:29 | u1 | provenance | | | testPathInjection.swift:519:9:519:20 | remoteString | testPathInjection.swift:529:28:529:39 | remoteString | provenance | | | testPathInjection.swift:519:9:519:20 | remoteString | testPathInjection.swift:541:32:541:43 | remoteString | provenance | | | testPathInjection.swift:519:9:519:20 | remoteString | testPathInjection.swift:542:38:542:49 | remoteString | provenance | | @@ -188,10 +119,6 @@ edges | testPathInjection.swift:519:9:519:20 | remoteString | testPathInjection.swift:559:35:559:46 | remoteString | provenance | | | testPathInjection.swift:519:9:519:20 | remoteString | testPathInjection.swift:560:41:560:52 | remoteString | provenance | | | testPathInjection.swift:519:24:519:78 | String(...) | testPathInjection.swift:519:9:519:20 | remoteString | provenance | | -| testPathInjection.swift:525:28:525:29 | u1 | testPathInjection.swift:16:74:16:77 | self | provenance | | -| testPathInjection.swift:525:28:525:29 | u1 | testPathInjection.swift:525:28:525:66 | ... .appendingPathComponent(...) | provenance | | -| testPathInjection.swift:525:28:525:66 | ... .appendingPathComponent(...) | testPathInjection.swift:16:74:16:77 | self | provenance | | -| testPathInjection.swift:525:28:525:66 | ... .appendingPathComponent(...) | testPathInjection.swift:525:28:525:93 | ... .appendingPathComponent(...) | provenance | | | testPathInjection.swift:546:5:546:6 | [post] s1 [pointee] | testPathInjection.swift:547:32:547:33 | s1 [pointee] | provenance | | | testPathInjection.swift:546:5:546:14 | ... .pointee | testPathInjection.swift:546:5:546:6 | [post] s1 [pointee] | provenance | | | testPathInjection.swift:546:18:546:29 | remoteString | testPathInjection.swift:546:5:546:14 | ... .pointee | provenance | | @@ -202,7 +129,6 @@ edges | testPathInjection.swift:580:9:580:20 | remoteString | testPathInjection.swift:588:22:588:33 | remoteString | provenance | | | testPathInjection.swift:580:24:580:78 | String(...) | testPathInjection.swift:580:9:580:20 | remoteString | provenance | | nodes -| testPathInjection.swift:16:74:16:77 | self | semmle.label | self | | testPathInjection.swift:340:9:340:20 | remoteString | semmle.label | remoteString | | testPathInjection.swift:340:24:340:78 | String(...) | semmle.label | String(...) | | testPathInjection.swift:351:34:351:45 | remoteString | semmle.label | remoteString | @@ -211,41 +137,15 @@ nodes | testPathInjection.swift:359:35:359:46 | remoteString | semmle.label | remoteString | | testPathInjection.swift:360:44:360:55 | remoteString | semmle.label | remoteString | | testPathInjection.swift:361:33:361:44 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:362:28:362:36 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:363:40:363:51 | remoteString | semmle.label | remoteString | | testPathInjection.swift:364:35:364:46 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:365:23:365:31 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:366:27:366:38 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:367:22:367:30 | remoteUrl | semmle.label | remoteUrl | -| testPathInjection.swift:368:30:368:38 | remoteUrl | semmle.label | remoteUrl | -| testPathInjection.swift:369:30:369:36 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:369:51:369:59 | remoteUrl | semmle.label | remoteUrl | -| testPathInjection.swift:371:13:371:21 | remoteUrl | semmle.label | remoteUrl | -| testPathInjection.swift:371:36:371:42 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:374:13:374:19 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:374:34:374:42 | remoteUrl | semmle.label | remoteUrl | -| testPathInjection.swift:376:21:376:29 | remoteUrl | semmle.label | remoteUrl | -| testPathInjection.swift:376:36:376:42 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:377:21:377:27 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:377:34:377:42 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:378:25:378:36 | remoteString | semmle.label | remoteString | | testPathInjection.swift:379:37:379:48 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:380:21:380:29 | remoteUrl | semmle.label | remoteUrl | -| testPathInjection.swift:380:36:380:42 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:381:21:381:27 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:381:34:381:42 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:382:25:382:36 | remoteString | semmle.label | remoteString | | testPathInjection.swift:383:37:383:48 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:384:31:384:39 | remoteUrl | semmle.label | remoteUrl | -| testPathInjection.swift:384:62:384:68 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:385:31:385:37 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:385:60:385:68 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:386:35:386:46 | remoteString | semmle.label | remoteString | | testPathInjection.swift:387:60:387:71 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:388:21:388:29 | remoteUrl | semmle.label | remoteUrl | -| testPathInjection.swift:388:36:388:42 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:389:21:389:27 | safeUrl | semmle.label | safeUrl | -| testPathInjection.swift:389:34:389:42 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:390:25:390:36 | remoteString | semmle.label | remoteString | | testPathInjection.swift:391:37:391:48 | remoteString | semmle.label | remoteString | | testPathInjection.swift:392:50:392:61 | remoteString | semmle.label | remoteString | @@ -256,34 +156,26 @@ nodes | testPathInjection.swift:398:38:398:49 | remoteString | semmle.label | remoteString | | testPathInjection.swift:399:51:399:62 | remoteString | semmle.label | remoteString | | testPathInjection.swift:400:43:400:54 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:401:34:401:42 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:403:50:403:61 | remoteString | semmle.label | remoteString | | testPathInjection.swift:404:42:404:53 | remoteString | semmle.label | remoteString | | testPathInjection.swift:405:40:405:51 | remoteString | semmle.label | remoteString | | testPathInjection.swift:406:43:406:54 | remoteString | semmle.label | remoteString | | testPathInjection.swift:407:60:407:71 | remoteString | semmle.label | remoteString | | testPathInjection.swift:408:50:408:61 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:412:26:412:34 | safeNsUrl | semmle.label | safeNsUrl | -| testPathInjection.swift:412:52:412:62 | remoteNsUrl | semmle.label | remoteNsUrl | | testPathInjection.swift:415:41:415:52 | remoteString | semmle.label | remoteString | | testPathInjection.swift:416:41:416:52 | remoteString | semmle.label | remoteString | | testPathInjection.swift:417:41:417:52 | remoteString | semmle.label | remoteString | | testPathInjection.swift:419:43:419:54 | remoteString | semmle.label | remoteString | | testPathInjection.swift:420:43:420:54 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:421:26:421:34 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:422:30:422:41 | remoteString | semmle.label | remoteString | | testPathInjection.swift:424:59:424:70 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:436:25:436:33 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:437:26:437:37 | remoteString | semmle.label | remoteString | | testPathInjection.swift:441:28:441:39 | remoteString | semmle.label | remoteString | | testPathInjection.swift:443:32:443:43 | remoteString | semmle.label | remoteString | | testPathInjection.swift:445:33:445:44 | remoteString | semmle.label | remoteString | | testPathInjection.swift:447:40:447:51 | remoteString | semmle.label | remoteString | | testPathInjection.swift:456:15:456:26 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:477:9:477:18 | remoteData | semmle.label | remoteData | -| testPathInjection.swift:477:22:477:87 | Data(...) | semmle.label | Data(...) | | testPathInjection.swift:482:22:482:33 | remoteString | semmle.label | remoteString | -| testPathInjection.swift:484:24:484:30 | buffer2 | semmle.label | buffer2 | | testPathInjection.swift:486:25:486:36 | remoteString | semmle.label | remoteString | | testPathInjection.swift:498:49:498:60 | remoteString | semmle.label | remoteString | | testPathInjection.swift:504:9:504:20 | remoteString | semmle.label | remoteString | @@ -292,10 +184,6 @@ nodes | testPathInjection.swift:512:33:512:44 | remoteString | semmle.label | remoteString | | testPathInjection.swift:519:9:519:20 | remoteString | semmle.label | remoteString | | testPathInjection.swift:519:24:519:78 | String(...) | semmle.label | String(...) | -| testPathInjection.swift:525:28:525:29 | u1 | semmle.label | u1 | -| testPathInjection.swift:525:28:525:66 | ... .appendingPathComponent(...) | semmle.label | ... .appendingPathComponent(...) | -| testPathInjection.swift:525:28:525:93 | ... .appendingPathComponent(...) | semmle.label | ... .appendingPathComponent(...) | -| testPathInjection.swift:527:28:527:29 | u1 | semmle.label | u1 | | testPathInjection.swift:529:28:529:39 | remoteString | semmle.label | remoteString | | testPathInjection.swift:541:32:541:43 | remoteString | semmle.label | remoteString | | testPathInjection.swift:542:38:542:49 | remoteString | semmle.label | remoteString | @@ -314,5 +202,3 @@ nodes | testPathInjection.swift:586:38:586:49 | remoteString | semmle.label | remoteString | | testPathInjection.swift:588:22:588:33 | remoteString | semmle.label | remoteString | subpaths -| testPathInjection.swift:525:28:525:29 | u1 | testPathInjection.swift:16:74:16:77 | self | testPathInjection.swift:16:74:16:77 | self | testPathInjection.swift:525:28:525:66 | ... .appendingPathComponent(...) | -| testPathInjection.swift:525:28:525:66 | ... .appendingPathComponent(...) | testPathInjection.swift:16:74:16:77 | self | testPathInjection.swift:16:74:16:77 | self | testPathInjection.swift:525:28:525:93 | ... .appendingPathComponent(...) | diff --git a/unified/ql/test/query-tests/security/CWE-022/PathInjection/testPathInjection.swift b/unified/ql/test/query-tests/security/CWE-022/PathInjection/testPathInjection.swift index 9cc20d430bdc..e21c3b994bab 100644 --- a/unified/ql/test/query-tests/security/CWE-022/PathInjection/testPathInjection.swift +++ b/unified/ql/test/query-tests/security/CWE-022/PathInjection/testPathInjection.swift @@ -359,34 +359,34 @@ func test(buffer1: UnsafeMutablePointer, buffer2: UnsafeMutablePointer()) // $ Alert - let _ = fm.replaceItemAt(remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: []) // $ Alert - let _ = fm.replaceItemAt(safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: []) // $ Alert + fm.trashItem(at: remoteUrl, resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ MISSING: Alert + let _ = fm.replaceItemAt(remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: []) // $ MISSING: Alert + let _ = fm.replaceItemAt(safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: []) // $ MISSING: Alert fm.replaceItem( - at: remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: [], // $ SPURIOUS: Alert + at: remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: [], resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ MISSING: Alert fm.replaceItem( - at: safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: [], // $ SPURIOUS: Alert + at: safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: [], resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ MISSING: Alert - fm.copyItem(at: remoteUrl, to: safeUrl) // $ Alert - fm.copyItem(at: safeUrl, to: remoteUrl) // $ Alert + fm.copyItem(at: remoteUrl, to: safeUrl) // $ MISSING: Alert + fm.copyItem(at: safeUrl, to: remoteUrl) // $ MISSING: Alert fm.copyItem(atPath: remoteString, toPath: "") // $ Alert fm.copyItem(atPath: "", toPath: remoteString) // $ Alert - fm.moveItem(at: remoteUrl, to: safeUrl) // $ Alert - fm.moveItem(at: safeUrl, to: remoteUrl) // $ Alert + fm.moveItem(at: remoteUrl, to: safeUrl) // $ MISSING: Alert + fm.moveItem(at: safeUrl, to: remoteUrl) // $ MISSING: Alert fm.moveItem(atPath: remoteString, toPath: "") // $ Alert fm.moveItem(atPath: "", toPath: remoteString) // $ Alert - fm.createSymbolicLink(at: remoteUrl, withDestinationURL: safeUrl) // $ Alert - fm.createSymbolicLink(at: safeUrl, withDestinationURL: remoteUrl) // $ Alert + fm.createSymbolicLink(at: remoteUrl, withDestinationURL: safeUrl) // $ MISSING: Alert + fm.createSymbolicLink(at: safeUrl, withDestinationURL: remoteUrl) // $ MISSING: Alert fm.createSymbolicLink(atPath: remoteString, withDestinationPath: "") // $ Alert fm.createSymbolicLink(atPath: "", withDestinationPath: remoteString) // $ Alert - fm.linkItem(at: remoteUrl, to: safeUrl) // $ Alert - fm.linkItem(at: safeUrl, to: remoteUrl) // $ Alert + fm.linkItem(at: remoteUrl, to: safeUrl) // $ MISSING: Alert + fm.linkItem(at: safeUrl, to: remoteUrl) // $ MISSING: Alert fm.linkItem(atPath: remoteString, toPath: "") // $ Alert fm.linkItem(atPath: "", toPath: remoteString) // $ Alert let _ = fm.destinationOfSymbolicLink(atPath: remoteString) // $ Alert @@ -398,7 +398,7 @@ func test(buffer1: UnsafeMutablePointer, buffer2: UnsafeMutablePointer, buffer2: UnsafeMutablePointer, buffer2: UnsafeMutablePointer, buffer2: UnsafeMutablePointer, buffer2: UnsafeMutablePointer Date: Fri, 2 Oct 2026 12:06:50 +0200 Subject: [PATCH 11/40] unified: Mostly restore path-injection results Switched to TaintTracking and adds some very ad-hoc steps to recover most of the results. Some more tests pass and others fail; these are now consistent with what we actually model. --- .../internal/dataflow/DataFlowPluginSwift.qll | 16 ++++ .../queries/security/CWE-022/PathInjection.ql | 2 +- .../PathInjection/PathInjectionTest.expected | 83 +++++++++++++++++++ .../PathInjection/testPathInjection.swift | 50 +++++------ 4 files changed, 125 insertions(+), 26 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll index ec03bf1536d3..fdabcc6eee71 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll @@ -25,5 +25,21 @@ private class SwiftDataFlowPlugin extends DataFlowPlugin { step.value() and node2.isResultValue(call) ) + or + // Taint flow through unary "!" (TODO: model as a read of Optional.some, possibly with implicit taint read) + exists(UnaryExpr expr | + expr.getOperator().(PostfixOperator).getValue() = "!" and + node1.isResultValue(expr.getOperand()) and + step.taint() and + node2.isResultValue(expr) + ) + or + // Taint flow through URL(string: x). TODO: Model with MaD and flow summaries + exists(CallExpr call | + call.getCallee().(Identifier).getValue() = ["URL", "NSURL"] and + node1.isResultValue(call.getNamedArgument("string")) and + step.taint() and + node2.isResultValue(call) + ) } } diff --git a/unified/ql/src/queries/security/CWE-022/PathInjection.ql b/unified/ql/src/queries/security/CWE-022/PathInjection.ql index 3ae09d533f1e..ecdd2ba3600f 100644 --- a/unified/ql/src/queries/security/CWE-022/PathInjection.ql +++ b/unified/ql/src/queries/security/CWE-022/PathInjection.ql @@ -54,7 +54,7 @@ module PathInjectionConfig implements DataFlow::ConfigSig { } } -module PathInjectionFlow = DataFlow::Global; +module PathInjectionFlow = TaintTracking::Global; import PathInjectionFlow::PathGraph diff --git a/unified/ql/test/query-tests/security/CWE-022/PathInjection/PathInjectionTest.expected b/unified/ql/test/query-tests/security/CWE-022/PathInjection/PathInjectionTest.expected index 90cd69557490..f80c567968ce 100644 --- a/unified/ql/test/query-tests/security/CWE-022/PathInjection/PathInjectionTest.expected +++ b/unified/ql/test/query-tests/security/CWE-022/PathInjection/PathInjectionTest.expected @@ -1,19 +1,39 @@ #select +| testPathInjection.swift:346:24:346:32 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:346:24:346:32 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:349:30:349:38 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:349:30:349:38 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:350:22:350:30 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:350:22:350:30 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:351:34:351:45 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:351:34:351:45 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:352:26:352:37 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:352:26:352:37 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:355:40:355:48 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:355:40:355:48 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:356:44:356:55 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:356:44:356:55 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:358:13:358:21 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:358:13:358:21 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:359:35:359:46 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:359:35:359:46 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:360:44:360:55 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:360:44:360:55 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:361:33:361:44 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:361:33:361:44 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:362:28:362:36 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:362:28:362:36 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:363:40:363:51 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:363:40:363:51 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:364:35:364:46 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:364:35:364:46 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:365:23:365:31 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:365:23:365:31 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:366:27:366:38 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:366:27:366:38 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:367:22:367:30 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:367:22:367:30 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:368:30:368:38 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:368:30:368:38 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:369:51:369:59 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:369:51:369:59 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:371:13:371:21 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:371:13:371:21 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:374:34:374:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:374:34:374:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:376:21:376:29 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:376:21:376:29 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:377:34:377:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:377:34:377:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:378:25:378:36 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:378:25:378:36 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:379:37:379:48 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:379:37:379:48 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:380:21:380:29 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:380:21:380:29 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:381:34:381:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:381:34:381:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:382:25:382:36 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:382:25:382:36 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:383:37:383:48 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:383:37:383:48 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:384:31:384:39 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:384:31:384:39 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:385:60:385:68 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:385:60:385:68 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:386:35:386:46 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:386:35:386:46 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:387:60:387:71 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:387:60:387:71 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:388:21:388:29 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:388:21:388:29 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:389:34:389:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:389:34:389:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:390:25:390:36 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:390:25:390:36 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:391:37:391:48 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:391:37:391:48 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:392:50:392:61 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:392:50:392:61 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | @@ -24,19 +44,24 @@ | testPathInjection.swift:398:38:398:49 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:398:38:398:49 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:399:51:399:62 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:399:51:399:62 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:400:43:400:54 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:400:43:400:54 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:401:34:401:42 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:401:34:401:42 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:403:50:403:61 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:403:50:403:61 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:404:42:404:53 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:404:42:404:53 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:405:40:405:51 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:405:40:405:51 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:406:43:406:54 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:406:43:406:54 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:407:60:407:71 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:407:60:407:71 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:408:50:408:61 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:408:50:408:61 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:410:26:410:36 | remoteNsUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:410:26:410:36 | remoteNsUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:412:52:412:62 | remoteNsUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:412:52:412:62 | remoteNsUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:415:41:415:52 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:415:41:415:52 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:416:41:416:52 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:416:41:416:52 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:417:41:417:52 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:417:41:417:52 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:419:43:419:54 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:419:43:419:54 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:420:43:420:54 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:420:43:420:54 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:421:26:421:34 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:421:26:421:34 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:422:30:422:41 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:422:30:422:41 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:424:59:424:70 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:424:59:424:70 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | +| testPathInjection.swift:436:25:436:33 | remoteUrl | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:436:25:436:33 | remoteUrl | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:437:26:437:37 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:437:26:437:37 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:441:28:441:39 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:441:28:441:39 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | | testPathInjection.swift:443:32:443:43 | remoteString | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:443:32:443:43 | remoteString | This path depends on a $@. | testPathInjection.swift:340:24:340:78 | String(...) | user-provided value | @@ -60,6 +85,8 @@ | testPathInjection.swift:586:38:586:49 | remoteString | testPathInjection.swift:580:24:580:78 | String(...) | testPathInjection.swift:586:38:586:49 | remoteString | This path depends on a $@. | testPathInjection.swift:580:24:580:78 | String(...) | user-provided value | | testPathInjection.swift:588:22:588:33 | remoteString | testPathInjection.swift:580:24:580:78 | String(...) | testPathInjection.swift:588:22:588:33 | remoteString | This path depends on a $@. | testPathInjection.swift:580:24:580:78 | String(...) | user-provided value | edges +| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:341:33:341:44 | remoteString | provenance | | +| testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:342:37:342:48 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:351:34:351:45 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:352:26:352:37 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:356:44:356:55 | remoteString | provenance | | @@ -108,6 +135,33 @@ edges | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:486:25:486:36 | remoteString | provenance | | | testPathInjection.swift:340:9:340:20 | remoteString | testPathInjection.swift:498:49:498:60 | remoteString | provenance | | | testPathInjection.swift:340:24:340:78 | String(...) | testPathInjection.swift:340:9:340:20 | remoteString | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:346:24:346:32 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:349:30:349:38 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:350:22:350:30 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:355:40:355:48 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:358:13:358:21 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:362:28:362:36 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:365:23:365:31 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:367:22:367:30 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:368:30:368:38 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:369:51:369:59 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:371:13:371:21 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:374:34:374:42 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:376:21:376:29 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:377:34:377:42 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:380:21:380:29 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:381:34:381:42 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:384:31:384:39 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:385:60:385:68 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:388:21:388:29 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:389:34:389:42 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:401:34:401:42 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:421:26:421:34 | remoteUrl | provenance | | +| testPathInjection.swift:341:9:341:17 | remoteUrl | testPathInjection.swift:436:25:436:33 | remoteUrl | provenance | | +| testPathInjection.swift:341:33:341:44 | remoteString | testPathInjection.swift:341:9:341:17 | remoteUrl | provenance | | +| testPathInjection.swift:342:9:342:19 | remoteNsUrl | testPathInjection.swift:410:26:410:36 | remoteNsUrl | provenance | | +| testPathInjection.swift:342:9:342:19 | remoteNsUrl | testPathInjection.swift:412:52:412:62 | remoteNsUrl | provenance | | +| testPathInjection.swift:342:37:342:48 | remoteString | testPathInjection.swift:342:9:342:19 | remoteNsUrl | provenance | | | testPathInjection.swift:504:9:504:20 | remoteString | testPathInjection.swift:510:37:510:48 | remoteString | provenance | | | testPathInjection.swift:504:9:504:20 | remoteString | testPathInjection.swift:512:33:512:44 | remoteString | provenance | | | testPathInjection.swift:504:24:504:78 | String(...) | testPathInjection.swift:504:9:504:20 | remoteString | provenance | | @@ -131,21 +185,45 @@ edges nodes | testPathInjection.swift:340:9:340:20 | remoteString | semmle.label | remoteString | | testPathInjection.swift:340:24:340:78 | String(...) | semmle.label | String(...) | +| testPathInjection.swift:341:9:341:17 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:341:33:341:44 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:342:9:342:19 | remoteNsUrl | semmle.label | remoteNsUrl | +| testPathInjection.swift:342:37:342:48 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:346:24:346:32 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:349:30:349:38 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:350:22:350:30 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:351:34:351:45 | remoteString | semmle.label | remoteString | | testPathInjection.swift:352:26:352:37 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:355:40:355:48 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:356:44:356:55 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:358:13:358:21 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:359:35:359:46 | remoteString | semmle.label | remoteString | | testPathInjection.swift:360:44:360:55 | remoteString | semmle.label | remoteString | | testPathInjection.swift:361:33:361:44 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:362:28:362:36 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:363:40:363:51 | remoteString | semmle.label | remoteString | | testPathInjection.swift:364:35:364:46 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:365:23:365:31 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:366:27:366:38 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:367:22:367:30 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:368:30:368:38 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:369:51:369:59 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:371:13:371:21 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:374:34:374:42 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:376:21:376:29 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:377:34:377:42 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:378:25:378:36 | remoteString | semmle.label | remoteString | | testPathInjection.swift:379:37:379:48 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:380:21:380:29 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:381:34:381:42 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:382:25:382:36 | remoteString | semmle.label | remoteString | | testPathInjection.swift:383:37:383:48 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:384:31:384:39 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:385:60:385:68 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:386:35:386:46 | remoteString | semmle.label | remoteString | | testPathInjection.swift:387:60:387:71 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:388:21:388:29 | remoteUrl | semmle.label | remoteUrl | +| testPathInjection.swift:389:34:389:42 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:390:25:390:36 | remoteString | semmle.label | remoteString | | testPathInjection.swift:391:37:391:48 | remoteString | semmle.label | remoteString | | testPathInjection.swift:392:50:392:61 | remoteString | semmle.label | remoteString | @@ -156,19 +234,24 @@ nodes | testPathInjection.swift:398:38:398:49 | remoteString | semmle.label | remoteString | | testPathInjection.swift:399:51:399:62 | remoteString | semmle.label | remoteString | | testPathInjection.swift:400:43:400:54 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:401:34:401:42 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:403:50:403:61 | remoteString | semmle.label | remoteString | | testPathInjection.swift:404:42:404:53 | remoteString | semmle.label | remoteString | | testPathInjection.swift:405:40:405:51 | remoteString | semmle.label | remoteString | | testPathInjection.swift:406:43:406:54 | remoteString | semmle.label | remoteString | | testPathInjection.swift:407:60:407:71 | remoteString | semmle.label | remoteString | | testPathInjection.swift:408:50:408:61 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:410:26:410:36 | remoteNsUrl | semmle.label | remoteNsUrl | +| testPathInjection.swift:412:52:412:62 | remoteNsUrl | semmle.label | remoteNsUrl | | testPathInjection.swift:415:41:415:52 | remoteString | semmle.label | remoteString | | testPathInjection.swift:416:41:416:52 | remoteString | semmle.label | remoteString | | testPathInjection.swift:417:41:417:52 | remoteString | semmle.label | remoteString | | testPathInjection.swift:419:43:419:54 | remoteString | semmle.label | remoteString | | testPathInjection.swift:420:43:420:54 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:421:26:421:34 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:422:30:422:41 | remoteString | semmle.label | remoteString | | testPathInjection.swift:424:59:424:70 | remoteString | semmle.label | remoteString | +| testPathInjection.swift:436:25:436:33 | remoteUrl | semmle.label | remoteUrl | | testPathInjection.swift:437:26:437:37 | remoteString | semmle.label | remoteString | | testPathInjection.swift:441:28:441:39 | remoteString | semmle.label | remoteString | | testPathInjection.swift:443:32:443:43 | remoteString | semmle.label | remoteString | diff --git a/unified/ql/test/query-tests/security/CWE-022/PathInjection/testPathInjection.swift b/unified/ql/test/query-tests/security/CWE-022/PathInjection/testPathInjection.swift index e21c3b994bab..9ada50020f56 100644 --- a/unified/ql/test/query-tests/security/CWE-022/PathInjection/testPathInjection.swift +++ b/unified/ql/test/query-tests/security/CWE-022/PathInjection/testPathInjection.swift @@ -343,50 +343,50 @@ func test(buffer1: UnsafeMutablePointer, buffer2: UnsafeMutablePointer()) // $ MISSING: Alert - let _ = fm.replaceItemAt(remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: []) // $ MISSING: Alert - let _ = fm.replaceItemAt(safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: []) // $ MISSING: Alert + fm.trashItem(at: remoteUrl, resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ Alert + let _ = fm.replaceItemAt(remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: []) // $ Alert + let _ = fm.replaceItemAt(safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: []) // $ Alert fm.replaceItem( - at: remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: [], + at: remoteUrl, withItemAt: safeUrl, backupItemName: nil, options: [], // $ SPURIOUS: Alert resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ MISSING: Alert fm.replaceItem( - at: safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: [], + at: safeUrl, withItemAt: remoteUrl, backupItemName: nil, options: [], // $ SPURIOUS: Alert resultingItemURL: AutoreleasingUnsafeMutablePointer()) // $ MISSING: Alert - fm.copyItem(at: remoteUrl, to: safeUrl) // $ MISSING: Alert - fm.copyItem(at: safeUrl, to: remoteUrl) // $ MISSING: Alert + fm.copyItem(at: remoteUrl, to: safeUrl) // $ Alert + fm.copyItem(at: safeUrl, to: remoteUrl) // $ Alert fm.copyItem(atPath: remoteString, toPath: "") // $ Alert fm.copyItem(atPath: "", toPath: remoteString) // $ Alert - fm.moveItem(at: remoteUrl, to: safeUrl) // $ MISSING: Alert - fm.moveItem(at: safeUrl, to: remoteUrl) // $ MISSING: Alert + fm.moveItem(at: remoteUrl, to: safeUrl) // $ Alert + fm.moveItem(at: safeUrl, to: remoteUrl) // $ Alert fm.moveItem(atPath: remoteString, toPath: "") // $ Alert fm.moveItem(atPath: "", toPath: remoteString) // $ Alert - fm.createSymbolicLink(at: remoteUrl, withDestinationURL: safeUrl) // $ MISSING: Alert - fm.createSymbolicLink(at: safeUrl, withDestinationURL: remoteUrl) // $ MISSING: Alert + fm.createSymbolicLink(at: remoteUrl, withDestinationURL: safeUrl) // $ Alert + fm.createSymbolicLink(at: safeUrl, withDestinationURL: remoteUrl) // $ Alert fm.createSymbolicLink(atPath: remoteString, withDestinationPath: "") // $ Alert fm.createSymbolicLink(atPath: "", withDestinationPath: remoteString) // $ Alert - fm.linkItem(at: remoteUrl, to: safeUrl) // $ MISSING: Alert - fm.linkItem(at: safeUrl, to: remoteUrl) // $ MISSING: Alert + fm.linkItem(at: remoteUrl, to: safeUrl) // $ Alert + fm.linkItem(at: safeUrl, to: remoteUrl) // $ Alert fm.linkItem(atPath: remoteString, toPath: "") // $ Alert fm.linkItem(atPath: "", toPath: remoteString) // $ Alert let _ = fm.destinationOfSymbolicLink(atPath: remoteString) // $ Alert @@ -398,7 +398,7 @@ func test(buffer1: UnsafeMutablePointer, buffer2: UnsafeMutablePointer, buffer2: UnsafeMutablePointer, buffer2: UnsafeMutablePointer, buffer2: UnsafeMutablePointer Date: Mon, 5 Oct 2026 09:30:02 +0200 Subject: [PATCH 12/40] ssa: Fix bad join order The C++ instantiation of DataFlowIntegration generated a bad join order --- shared/ssa/codeql/ssa/Ssa.qll | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/shared/ssa/codeql/ssa/Ssa.qll b/shared/ssa/codeql/ssa/Ssa.qll index 7f05e5c006a1..395738e3368d 100644 --- a/shared/ssa/codeql/ssa/Ssa.qll +++ b/shared/ssa/codeql/ssa/Ssa.qll @@ -1776,20 +1776,21 @@ module Make< final class ExprPostUpdateNode = ExprPostUpdateNodeImpl; - private class ReadNodeImpl extends ExprNodeImpl { - private BasicBlock bb_; - private int i_; + pragma[nomagic] + private predicate exprReadAt( + DfInput::Expr e, BasicBlock bb, int i, SourceVariable v, boolean isPost, TExprNode node + ) { + variableRead(bb, i, v, true) and + e.hasCfgNode(bb, i) and + node = TExprNode(e, v, isPost) + } - ReadNodeImpl() { - variableRead(bb_, i_, v_, true) and - this.getExpr().hasCfgNode(bb_, i_) - } + private class ReadNodeImpl extends ExprNodeImpl { + ReadNodeImpl() { exprReadAt(e, _, _, _, false, this) } pragma[nomagic] predicate readsAt(BasicBlock bb, int i, SourceVariable v) { - bb = bb_ and - i = i_ and - v = v_ + exprReadAt(e, bb, i, v, false, this) } } From 42ed40cc9f8e069ee3b3d67c3f27af0da9145d9d Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Sep 2026 11:58:03 +0200 Subject: [PATCH 13/40] unified: Add some tests with captured vars --- .../test/library-tests/dataflow/capture.swift | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 unified/ql/test/library-tests/dataflow/capture.swift diff --git a/unified/ql/test/library-tests/dataflow/capture.swift b/unified/ql/test/library-tests/dataflow/capture.swift new file mode 100644 index 000000000000..320a1b76472a --- /dev/null +++ b/unified/ql/test/library-tests/dataflow/capture.swift @@ -0,0 +1,71 @@ +func source(_ s: String) -> String { return s } + +@discardableResult +func sink(_ s: String) -> String { + print(s) + return "" +} + +func t1() { + let x = source("t1.1") + let closure = { (_: Int) in + sink(x) // $ MISSING: hasValueFlow="t1.1" + } + closure(123) +} + +func t2() { + var x = "safe" + let closure = { (arg: Int) in + x = source("t2.1") + } + sink(x) // no flow + closure(123) + sink(x) // $ MISSING: hasValueFlow="t2.1" +} + +func t3() { + let x = source("t3.1") + var y1 = "safe" + var y2 = "safe" + let closure = { (arg: Int) in + y1 = x + y2 = x + "blah" + } + sink(y1) // no flow + sink(y2) // no flow + closure(123) + sink(y1) // $ MISSING: hasValueFlow="t3.1" + sink(y2) // $ MISSING: hasTaintFlow="t3.1" +} + +func t4() { + let x = source("t4.1") + var y = "safe" + let closure = { (arg: String) in + y = arg + } + sink(y) // no flow + closure(x) + sink(y) // $ MISSING: hasValueFlow="t4.1" +} + +func t5() { + let x = source("t5.1") + var y = ("safe", "safe") + let closure = { (arg: String) in + y.0 = arg + } + sink(y.0) // no flow + closure(x) + sink(y.0) // $ MISSING: hasValueFlow="t5.1" +} + +func t6() { + var x = "safe" + let closure = { (_: Int) in + sink(x) // $ MISSING: hasValueFlow="t6.1" + } + x = source("t6.1") + closure(123) +} From 7505379f1cbfcdc7e5c4e77e9022948c7a0d6686 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Sep 2026 14:55:22 +0200 Subject: [PATCH 14/40] unified: Split Node into "stage 1" and "final stage" --- .../internal/dataflow/DataFlowGraph.qll | 2 +- .../dataflow/DataFlowInstantiation.qll | 4 +- .../internal/dataflow/DataFlowNode.qll | 163 +++++++++++++----- .../internal/dataflow/DataFlowPlugin.qll | 2 +- .../internal/dataflow/DataFlowPluginSwift.qll | 2 +- 5 files changed, 126 insertions(+), 47 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll index 91111f7f8c0d..d38d7466a3b5 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll @@ -2,7 +2,7 @@ private import unified private import AllDataFlow private import codeql.unified.internal.LocalNameBinding -predicate step(Node node1, Step step, Node node2) { +predicate step(BuilderNode node1, Step step, BuilderNode node2) { any(DataFlowPlugin p).step(node1, step, node2) or exists(Callable callable | diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll index c762ec0de7d0..0e2b28a8d7a3 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll @@ -57,7 +57,7 @@ module DataFlowInput implements InputSig { pos.asNamed() = param.getExternalName() ) or - p.isReceiverParameterEx(c) and + p.(BuilderNode).isReceiverParameterEx(c) and pos.isReceiver() } @@ -80,7 +80,7 @@ module DataFlowInput implements InputSig { pos.asNamed() = arg.getName() ) or - n.isReceiverArgumentEx(call) and + n.(BuilderNode).isReceiverArgumentEx(call) and pos.isReceiver() } diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll index 0c92899205c2..4534b027439c 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll @@ -81,14 +81,20 @@ newtype TDataFlowNode = TLocalVariableRefNode(AstNode repr, LocalVariable var, VariableRefKind kind) { performsVariableAccess(repr, var, kind, _) } or - TLocalSsaNode(LocalSsaDataFlowOutput::SsaNode node) or TReceiverParameterNode(DataFlowCallable callable) or - TReceiverArgumentNode(DataFlowCall call, Boolean isPost) + TReceiverArgumentNode(DataFlowCall call, Boolean isPost) or + TLocalSsaNode(LocalSsaDataFlowOutput::SsaNode node) + +class TDataFlowNodeStage1 = + TValueNode or TStrictlyIncomingValue or TExprPostUpdateNode or TLocalVariableRefNode or + TReceiverParameterNode or TReceiverArgumentNode; /** - * A node representing something that can have a value. + * A data-flow node used during construction of the local data flow graph. + * + * This only contains nodes that are materialised in "stage 1". */ -class Node extends TDataFlowNode { +class BuilderNode extends TDataFlowNodeStage1 { /** Holds if this is the result of evaluating `expr`. */ pragma[nomagic] predicate isResultValue(Expr expr) { hasResultValue(expr) and this = TValueNode(expr) } @@ -134,7 +140,8 @@ class Node extends TDataFlowNode { * this node still exists but will typically not flow anywhere. */ predicate isReceiverParameter(Callable callable) { - this.isReceiverParameterEx(any(DataFlowCallable c | c.asSourceCallable() = callable)) + this.(BuilderNode) + .isReceiverParameterEx(any(DataFlowCallable c | c.asSourceCallable() = callable)) } /** @@ -168,23 +175,44 @@ class Node extends TDataFlowNode { this = TReceiverArgumentNode(call, isPost) } - /** Gets the expression represented by this node. */ - Expr asExpr() { this = TValueNode(result) } + /** + * Gets the post-update node for this node, if any. + * + * The post-update node represents the updated state of the value held in this node, after it has been mutated by the surrounding assignment or call. + */ + pragma[nomagic] + BuilderNode getPostUpdateNode() { + exists(Expr expr | + this.isResultValue(expr) and + result.isPostUpdate(expr) + ) + or + exists(Expr expr, LocalVariable var | + this.isLocalVariableRead(expr, var) and + result.isLocalVariablePostUpdate(expr, var) + ) + or + exists(DataFlowCall call | + this.isReceiverArgumentEx(call) and + result.isReceiverPostUpdateEx(call) + ) + } /** * Gets the AST node wrapped by this data flow, if any. */ AstNode getWrappedAstNode() { - result = this.asExpr() or + this = TValueNode(result) or this = TStrictlyIncomingValue(result) or this = TExprPostUpdateNode(result) } /** Get a string representation of this element. */ string toString() { - result = this.asExpr().toString() - or exists(Expr expr | + this = TValueNode(expr) and + result = expr.toString() + or this = TStrictlyIncomingValue(expr) and result = "[incoming] " + expr.toString() or @@ -197,11 +225,6 @@ class Node extends TDataFlowNode { result = "[variable " + kind + "] " + v.toString() ) or - exists(LocalSsaDataFlowOutput::SsaNode node | - this = TLocalSsaNode(node) and - result = node.toString() - ) - or exists(DataFlowCallable callable | this.isReceiverParameterEx(callable) and result = "[receiver] " + callable.toString() @@ -225,11 +248,6 @@ class Node extends TDataFlowNode { result = repr.getLocation() ) or - exists(LocalSsaDataFlowOutput::SsaNode node | - this = TLocalSsaNode(node) and - result = node.getLocation() - ) - or exists(DataFlowCallable callable | this.isReceiverParameterEx(callable) and result = callable.getLocation() @@ -240,6 +258,83 @@ class Node extends TDataFlowNode { result = call.getLocation() ) } +} + +class Node extends TDataFlowNode { + /** Gets the expression represented by this node. */ + Expr asExpr() { this = TValueNode(result) } + + /** Holds if this is the result of evaluating `expr`. */ + pragma[nomagic] + predicate isResultValue(Expr expr) { this.(BuilderNode).isResultValue(expr) } + + /** Holds if this represents the value about to be assigned to `expr` or pattern-matched against `expr`. */ + pragma[nomagic] + predicate isIncomingValue(Expr expr) { this.(BuilderNode).isIncomingValue(expr) } + + /** Holds if this represents the reference to `v` at `repr`. */ + predicate isLocalVariableRef(AstNode repr, LocalVariable v, VariableRefKind kind) { + this.(BuilderNode).isLocalVariableRef(repr, v, kind) + } + + /** Holds if this represents the value read from `v` at `repr`. */ + predicate isLocalVariableRead(AstNode repr, LocalVariable v) { + this.(BuilderNode).isLocalVariableRead(repr, v) + } + + /** Holds if this represents the value written to `v` at `repr`. */ + predicate isLocalVariableWrite(AstNode repr, LocalVariable v) { + this.(BuilderNode).isLocalVariableWrite(repr, v) + } + + /** Holds if this represents the updated state of the value held in `v` after it has been mutated by the surrounding assignment or call. */ + predicate isLocalVariablePostUpdate(AstNode repr, LocalVariable v) { + this.(BuilderNode).isLocalVariablePostUpdate(repr, v) + } + + /** Holds if this represents the updated state of the value returned by `expr` after it has been mutated by the surrounding assignment or call. */ + predicate isPostUpdate(Expr expr) { this.(BuilderNode).isPostUpdate(expr) } + + /** + * Holds if this represents the receiver passed to the given callable. + * + * Note that for non-methods and closures that capture the receiver from the enclosing method, + * this node still exists but will typically not flow anywhere. + */ + predicate isReceiverParameter(Callable callable) { + this.(BuilderNode).isReceiverParameter(callable) + } + + /** Holds if this node represents the receiver argument passed to `call`. */ + predicate isReceiverArgument(CallExpr call) { this.(BuilderNode).isReceiverArgument(call) } + + /** Holds if this node represents the updated state of the receiver of `call` after the call returns. */ + predicate isReceiverPostUpdate(CallExpr call) { this.(BuilderNode).isReceiverPostUpdate(call) } + + /** + * Gets the AST node wrapped by this data flow, if any. + */ + AstNode getWrappedAstNode() { result = this.(BuilderNode).getWrappedAstNode() } + + /** Get a string representation of this element. */ + string toString() { + result = this.(BuilderNode).toString() + or + exists(LocalSsaDataFlowOutput::SsaNode node | + this = TLocalSsaNode(node) and + result = node.toString() + ) + } + + /** Gets the location of this data flow node. */ + Location getLocation() { + result = this.(BuilderNode).getLocation() + or + exists(LocalSsaDataFlowOutput::SsaNode node | + this = TLocalSsaNode(node) and + result = node.getLocation() + ) + } /** Gets the data-flow callable containing this data flow node. */ DataFlowCallable getEnclosingCallableEx() { @@ -256,10 +351,10 @@ class Node extends TDataFlowNode { result.asSourceCallable() = node.getSourceVariable().getDeclaringCallable() ) or - this.isReceiverParameterEx(result) + this.(BuilderNode).isReceiverParameterEx(result) or exists(DataFlowCall call | - this.isReceiverArgumentEx(call, _) and + this.(BuilderNode).isReceiverArgumentEx(call, _) and result = call.getEnclosingCallable() ) } @@ -292,16 +387,16 @@ class Node extends TDataFlowNode { ) or exists(DataFlowCallable callable | - this.isReceiverParameterEx(callable) and + this.(BuilderNode).isReceiverParameterEx(callable) and cfgNode.(ControlFlow::EntryNode).getEnclosingCallable() = callable.asSourceCallable() ) or exists(DataFlowCall call, CallExpr sourceCall | call.asExplicitCall() = sourceCall and ( - this.isReceiverArgumentEx(call) and cfgNode.injects(sourceCall) + this.(BuilderNode).isReceiverArgumentEx(call) and cfgNode.injects(sourceCall) or - this.isReceiverPostUpdateEx(call) and cfgNode.isAfter(sourceCall) + this.(BuilderNode).isReceiverPostUpdateEx(call) and cfgNode.isAfter(sourceCall) ) ) ) @@ -321,21 +416,5 @@ class Node extends TDataFlowNode { * * The post-update node represents the updated state of the value held in this node, after it has been mutated by the surrounding assignment or call. */ - pragma[nomagic] - Node getPostUpdateNode() { - exists(Expr expr | - this.isResultValue(expr) and - result.isPostUpdate(expr) - ) - or - exists(Expr expr, LocalVariable var | - this.isLocalVariableRead(expr, var) and - result.isLocalVariablePostUpdate(expr, var) - ) - or - exists(DataFlowCall call | - this.isReceiverArgumentEx(call) and - result.isReceiverPostUpdateEx(call) - ) - } + Node getPostUpdateNode() { result = this.(BuilderNode).getPostUpdateNode() } } diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPlugin.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPlugin.qll index 01b480e5af74..70b45b8c092a 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPlugin.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPlugin.qll @@ -12,5 +12,5 @@ private module Plugins { class DataFlowPlugin extends Unit { /** Holds if there is a language-specific step from `node1 -> step -> node2`. */ - predicate step(Node node1, Step step, Node node2) { none() } + predicate step(BuilderNode node1, Step step, BuilderNode node2) { none() } } diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll index fdabcc6eee71..df43d694f95e 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll @@ -7,7 +7,7 @@ private import AllDataFlow private class SwiftDataFlowPlugin extends DataFlowPlugin { // Note: For now we assume all code is Swift, but in the future we must restrict these rules to Swift-files - override predicate step(Node node1, Step step, Node node2) { + override predicate step(BuilderNode node1, Step step, BuilderNode node2) { exists(BinaryExpr expr | expr.getOperator().getValue() = ["+", "+="] and node1.isResultValue([expr.getLeft(), expr.getRight()]) and From 6348a8a3634dcf91c4e7327dd5c8fe04352d1271 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Sep 2026 12:55:25 +0200 Subject: [PATCH 15/40] unified: Factor out LocalVariableRefNode --- .../unified/internal/dataflow/AllDataFlow.qll | 1 + .../unified/internal/dataflow/LocalSsa.qll | 17 +------------ .../dataflow/LocalVariableRefNode.qll | 25 +++++++++++++++++++ 3 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 unified/ql/lib/codeql/unified/internal/dataflow/LocalVariableRefNode.qll diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll b/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll index 0d44eea6cb1e..c8847276c828 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll @@ -13,3 +13,4 @@ import ParameterPositions import Step import TaintTrackingInstantiation import VariableRefKind +import LocalVariableRefNode diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll b/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll index dd3b41492061..4fccf5065fa0 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll @@ -38,22 +38,7 @@ module LocalSsaOutput = Make; private import LocalSsaOutput module LocalSsaDataFlowInput implements DataFlowIntegrationInputSig { - class Expr extends TLocalVariableRefNode { - U::AstNode repr; - LocalVariable var; - VariableRefKind kind; - - Expr() { this = TLocalVariableRefNode(repr, var, kind) } - - predicate hasCfgNode(BasicBlock bb, int i) { - this = TLocalVariableRefNode(repr, var, kind) and - // Note: the synthetic read we insert for post-updates must also have an Expr - (kind.isRead() or kind.isPostUpdate()) and - performsVariableAccess(repr, var, kind, bb.getNode(i)) - } - - string toString() { result = this.(Node).toString() } - } + class Expr = LocalVariableRefNode; class GuardValue = Void; diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/LocalVariableRefNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/LocalVariableRefNode.qll new file mode 100644 index 000000000000..6d54df58f9bd --- /dev/null +++ b/unified/ql/lib/codeql/unified/internal/dataflow/LocalVariableRefNode.qll @@ -0,0 +1,25 @@ +private import unified +private import AllDataFlow + +/** + * A reference to a local variable (read, write, or post-update). + * + * This is backed by same entity as the corresponding data-flow node, but is referenced before + * the full `Node` type has been materialised (during SSA construction). + */ +class LocalVariableRefNode extends BuilderNode, TLocalVariableRefNode { + private AstNode repr; + private LocalVariable var; + private VariableRefKind kind; + + LocalVariableRefNode() { this = TLocalVariableRefNode(repr, var, kind) } + + predicate hasCfgNode(BasicBlock bb, int i) { + this = TLocalVariableRefNode(repr, var, kind) and + performsVariableAccess(repr, var, kind, bb.getNode(i)) + } + + LocalVariable getVariable() { result = var } + + VariableRefKind getRefKind() { result = kind } +} From d2a40ae33240f64ebd1ee4f6f1a40c46a7a68e2b Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Sep 2026 15:01:17 +0200 Subject: [PATCH 16/40] unified: Add canonical callable node --- .../internal/dataflow/DataFlowNode.qll | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll index 4534b027439c..5722fb4b03a7 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll @@ -81,13 +81,14 @@ newtype TDataFlowNode = TLocalVariableRefNode(AstNode repr, LocalVariable var, VariableRefKind kind) { performsVariableAccess(repr, var, kind, _) } or + TCallableNode(DataFlowCallable callable) or TReceiverParameterNode(DataFlowCallable callable) or TReceiverArgumentNode(DataFlowCall call, Boolean isPost) or TLocalSsaNode(LocalSsaDataFlowOutput::SsaNode node) class TDataFlowNodeStage1 = TValueNode or TStrictlyIncomingValue or TExprPostUpdateNode or TLocalVariableRefNode or - TReceiverParameterNode or TReceiverArgumentNode; + TCallableNode or TReceiverParameterNode or TReceiverArgumentNode; /** * A data-flow node used during construction of the local data flow graph. @@ -175,6 +176,14 @@ class BuilderNode extends TDataFlowNodeStage1 { this = TReceiverArgumentNode(call, isPost) } + /** Holds if this is the canonical representative for the given `callable`. */ + predicate isCallableEx(DataFlowCallable callable) { this = TCallableNode(callable) } + + /** Holds if this is the canonical representative for the given `callable`. */ + predicate isCallable(Callable callable) { + this = TCallableNode(any(DataFlowCallable c | c.asSourceCallable() = callable)) + } + /** * Gets the post-update node for this node, if any. * @@ -228,6 +237,9 @@ class BuilderNode extends TDataFlowNodeStage1 { exists(DataFlowCallable callable | this.isReceiverParameterEx(callable) and result = "[receiver] " + callable.toString() + or + this.isCallableEx(callable) and + result = "[callable] " + callable.toString() ) or exists(DataFlowCall call | @@ -249,7 +261,10 @@ class BuilderNode extends TDataFlowNodeStage1 { ) or exists(DataFlowCallable callable | - this.isReceiverParameterEx(callable) and + this.isReceiverParameterEx(callable) + or + this.isCallableEx(callable) + | result = callable.getLocation() ) or @@ -311,6 +326,12 @@ class Node extends TDataFlowNode { /** Holds if this node represents the updated state of the receiver of `call` after the call returns. */ predicate isReceiverPostUpdate(CallExpr call) { this.(BuilderNode).isReceiverPostUpdate(call) } + /** Holds if this is the canonical representative for the given `callable`. */ + predicate isCallableEx(DataFlowCallable callable) { this.(BuilderNode).isCallableEx(callable) } + + /** Holds if this is the canonical representative for the given `callable`. */ + predicate isCallable(Callable callable) { this.(BuilderNode).isCallable(callable) } + /** * Gets the AST node wrapped by this data flow, if any. */ @@ -357,6 +378,11 @@ class Node extends TDataFlowNode { this.(BuilderNode).isReceiverArgumentEx(call, _) and result = call.getEnclosingCallable() ) + or + exists(DataFlowCallable callable | + this.isCallableEx(callable) and + result.asSourceCallable() = callable.asSourceCallable().getEnclosingCallable() + ) } /** Gets the callable containing this data flow node. */ @@ -389,6 +415,9 @@ class Node extends TDataFlowNode { exists(DataFlowCallable callable | this.(BuilderNode).isReceiverParameterEx(callable) and cfgNode.(ControlFlow::EntryNode).getEnclosingCallable() = callable.asSourceCallable() + or + this.isCallableEx(callable) and + cfgNode.injects(callable.asSourceCallable()) ) or exists(DataFlowCall call, CallExpr sourceCall | From 0be7e5759ef69e7ed47923bf4476121ccaf8d8dd Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Sep 2026 16:28:54 +0200 Subject: [PATCH 17/40] unified: Exclude function types from DataFlowCallable --- .../lib/codeql/unified/internal/dataflow/DataFlowCallable.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll index 7e31a0b45e0e..8b67a7206ef5 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll @@ -1,7 +1,9 @@ private import unified private import AllDataFlow +private import codeql.unified.internal.ExprPositions -private newtype TDataFlowCallable = TSourceCallable(Callable callable) +private newtype TDataFlowCallable = + TSourceCallable(Callable callable) { not isInTypeContext(callable) } /** * A callable entity: either a function-like entity in source code or From 3bb8efb582b68643289fa3dc8d6f3fba7f0d0aeb Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Sep 2026 16:43:45 +0200 Subject: [PATCH 18/40] unified: Function declaration names belong to the outer scope --- .../unified/internal/ControlFlowGraph.qll | 2 + .../lib/codeql/unified/internal/FacadeAst.qll | 6 + .../controlflow/basicblock-slices.expected | 114 +++++++++--------- .../library-tests/controlflow/cfg.expected | 20 ++- .../test/library-tests/controlflow/cfg.swift | 12 +- .../local-name-binding/test.swift | 2 +- 6 files changed, 79 insertions(+), 77 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/ControlFlowGraph.qll b/unified/ql/lib/codeql/unified/internal/ControlFlowGraph.qll index a6f7e288ef80..6c7b55e70991 100644 --- a/unified/ql/lib/codeql/unified/internal/ControlFlowGraph.qll +++ b/unified/ql/lib/codeql/unified/internal/ControlFlowGraph.qll @@ -43,6 +43,8 @@ module Ast implements AstSig { not skipControlFlow(result) or n.(FunctionExpr).getCaptureDeclaration(index) = result + or + n.(FunctionDeclaration).getNameNode() = result and index = 0 } Callable getEnclosingCallable(AstNode node) { result = node.getEnclosingCallable() } diff --git a/unified/ql/lib/codeql/unified/internal/FacadeAst.qll b/unified/ql/lib/codeql/unified/internal/FacadeAst.qll index e8b027066b16..38258a957fc1 100644 --- a/unified/ql/lib/codeql/unified/internal/FacadeAst.qll +++ b/unified/ql/lib/codeql/unified/internal/FacadeAst.qll @@ -54,6 +54,12 @@ module Unified { this = func.getACaptureDeclaration() and result = func.getParent() ) + or + exists(FunctionDeclaration func | + // The name of a function declaration is a variable belonging to the enclosing callable. + this = func.getNameNode() and + result = func.getParent() + ) } /** diff --git a/unified/ql/test/library-tests/controlflow/basicblock-slices.expected b/unified/ql/test/library-tests/controlflow/basicblock-slices.expected index b6a0308729fc..54af0ebd43a6 100644 --- a/unified/ql/test/library-tests/controlflow/basicblock-slices.expected +++ b/unified/ql/test/library-tests/controlflow/basicblock-slices.expected @@ -1,7 +1,7 @@ | 1 | cfg.swift:1:1:604:1 | Block | 'Block -V var topLevelDecl -V topLevelDecl -> Int -> 0' | | 2 | cfg.swift:2:1:2:1 | 0 | '0' | | 3 | cfg.swift:3:1:3:12 | topLevelDecl | 'topLevelDecl -> 1 -^ ... + ...' | -| 5 | cfg.swift:5:1:5:37 | func returnZero | 'func returnZero' | +| 5 | cfg.swift:5:1:5:37 | func returnZero | 'func returnZero -V returnZero' | | 5 | cfg.swift:5:26:5:37 | Block | 'Block -V 0 -^ ReturnExpr' | | 7 | cfg.swift:7:1:7:10 | returnZero | 'returnZero -^ returnZero(...)' | | 8 | cfg.swift:8:1:8:6 | Double | 'Double -> Argument -V topLevelDecl -^ Double(...)' | @@ -9,10 +9,10 @@ | 11 | cfg.swift:11:10:11:15 | error1 | 'error1 -V error1 -> error2 -V error2' | | 12 | cfg.swift:12:10:12:31 | error3 | 'error3 -V error3 -^ ' | | 12 | cfg.swift:12:17:12:25 | withParam | 'withParam -? Block' | -| 15 | cfg.swift:15:1:17:1 | func isZero | 'func isZero' | +| 15 | cfg.swift:15:1:17:1 | func isZero | 'func isZero -V isZero' | | 15 | cfg.swift:15:13:15:13 | x | 'x -> Block' | | 16 | cfg.swift:16:10:16:10 | x | 'x -> 0 -^ ... == ... -^ ReturnExpr' | -| 19 | cfg.swift:19:1:26:1 | func mightThrow | 'func mightThrow' | +| 19 | cfg.swift:19:1:26:1 | func mightThrow | 'func mightThrow -V mightThrow' | | 19 | cfg.swift:19:17:19:17 | x | 'x -> Block' | | 20 | cfg.swift:20:3:22:3 | GuardIfStmt | 'GuardIfStmt -V x -> 0 -^ ... >= ...' | | 20 | cfg.swift:20:21:22:3 | Block | 'Block' | @@ -20,7 +20,7 @@ | 23 | cfg.swift:23:3:25:3 | GuardIfStmt | 'GuardIfStmt -V x -> 0 -^ ... <= ...' | | 23 | cfg.swift:23:21:25:3 | Block | 'Block' | | 24 | cfg.swift:24:11:24:17 | MyError | 'MyError -^ ... .error3 -> Argument -V x -> 1 -^ ... + ... -^ ... .error3(...) -^ ThrowExpr' | -| 28 | cfg.swift:28:1:45:1 | func tryCatch | 'func tryCatch' | +| 28 | cfg.swift:28:1:45:1 | func tryCatch | 'func tryCatch -V tryCatch' | | 28 | cfg.swift:28:15:28:15 | x | 'x -> Block' | | 29 | cfg.swift:29:3:43:3 | TryExpr | 'TryExpr -V Block' | | 30 | cfg.swift:30:5:30:24 | try ... | 'try ...' | @@ -40,41 +40,41 @@ | 41 | cfg.swift:41:5:43:3 | CatchClause | 'CatchClause -V Block' | | 42 | cfg.swift:42:5:42:9 | print | 'print -> Argument -V Unknown error -> interpolation -> Argument -V error -^ interpolation(...) -> -^ StringInterpolationExpr -^ print(...)' | | 44 | cfg.swift:44:10:44:10 | 0 | '0 -^ ReturnExpr' | -| 47 | cfg.swift:47:1:51:1 | func createClosure1 | 'func createClosure1' | +| 47 | cfg.swift:47:1:51:1 | func createClosure1 | 'func createClosure1 -V createClosure1' | | 47 | cfg.swift:47:21:47:21 | s | 's -> Block' | | 48 | cfg.swift:48:10:50:3 | FunctionExpr | 'FunctionExpr -^ ReturnExpr' | | 49 | cfg.swift:49:5:49:17 | Block | 'Block -V s -> "" -^ ... + ... -^ ReturnExpr' | -| 53 | cfg.swift:53:1:58:1 | func createClosure2 | 'func createClosure2' | +| 53 | cfg.swift:53:1:58:1 | func createClosure2 | 'func createClosure2 -V createClosure2' | | 53 | cfg.swift:53:21:53:21 | x | 'x -> Block' | -| 54 | cfg.swift:54:3:56:3 | func f | 'func f' | +| 54 | cfg.swift:54:3:56:3 | func f | 'func f -V f' | | 54 | cfg.swift:54:10:54:10 | y | 'y -> Block' | | 55 | cfg.swift:55:12:55:12 | x | 'x -> y -^ ... + ... -^ ReturnExpr' | | 57 | cfg.swift:57:10:57:10 | f | 'f -^ ReturnExpr' | -| 60 | cfg.swift:60:1:64:1 | func createClosure3 | 'func createClosure3' | +| 60 | cfg.swift:60:1:64:1 | func createClosure3 | 'func createClosure3 -V createClosure3' | | 60 | cfg.swift:60:21:60:21 | x | 'x -> Block' | | 61 | cfg.swift:61:10:63:3 | FunctionExpr | 'FunctionExpr -^ ReturnExpr' | | 62 | cfg.swift:62:6:62:6 | y | 'y -> Block -V x -> y -^ ... + ...' | -| 66 | cfg.swift:66:1:70:1 | func callClosures | 'func callClosures' | +| 66 | cfg.swift:66:1:70:1 | func callClosures | 'func callClosures -V callClosures' | | 66 | cfg.swift:66:21:70:1 | Block | 'Block' | | 67 | cfg.swift:67:3:67:34 | var x1 | 'var x1 -V x1 -> createClosure1 -> Argument -V "" -^ createClosure1(...) -^ ...(...)' | | 68 | cfg.swift:68:3:68:35 | var x2 | 'var x2 -V x2 -> createClosure2 -> Argument -V 0 -^ createClosure2(...) -> Argument -V 10 -^ ...(...)' | | 69 | cfg.swift:69:3:69:35 | var x3 | 'var x3 -V x3 -> createClosure3 -> Argument -V 0 -^ createClosure3(...) -> Argument -V 10 -^ ...(...)' | -| 72 | cfg.swift:72:1:75:1 | func maybeParseInt | 'func maybeParseInt' | +| 72 | cfg.swift:72:1:75:1 | func maybeParseInt | 'func maybeParseInt -V maybeParseInt' | | 72 | cfg.swift:72:20:72:20 | s | 's -> Block' | | 73 | cfg.swift:73:3:73:23 | var n | 'var n -V n -> Optional -> Int -^ GenericTypeExpr -> Int -> Argument -V s -^ Int(...)' | | 74 | cfg.swift:74:10:74:10 | n | 'n -^ ReturnExpr' | -| 77 | cfg.swift:77:1:81:1 | func forceAndBackToOptional | 'func forceAndBackToOptional' | +| 77 | cfg.swift:77:1:81:1 | func forceAndBackToOptional | 'func forceAndBackToOptional -V forceAndBackToOptional' | | 77 | cfg.swift:77:39:81:1 | Block | 'Block' | | 78 | cfg.swift:78:3:78:36 | var nBang | 'var nBang -V nBang -> maybeParseInt -> Argument -V "42" -^ maybeParseInt(...) -^ ... !' | | 79 | cfg.swift:79:3:79:31 | var n | 'var n -V n -> maybeParseInt -> Argument -V "42" -^ maybeParseInt(...)' | | 80 | cfg.swift:80:10:80:14 | nBang | 'nBang -> n -^ ... ! -^ ... + ... -^ ReturnExpr' | -| 83 | cfg.swift:83:1:98:1 | func testInOut | 'func testInOut' | +| 83 | cfg.swift:83:1:98:1 | func testInOut | 'func testInOut -V testInOut' | | 83 | cfg.swift:83:25:98:1 | Block | 'Block' | | 84 | cfg.swift:84:3:84:15 | var temp | 'var temp -V temp -> 10' | -| 86 | cfg.swift:86:3:88:3 | func add | 'func add' | +| 86 | cfg.swift:86:3:88:3 | func add | 'func add -V add' | | 86 | cfg.swift:86:12:86:12 | a | 'a -> Block' | | 87 | cfg.swift:87:5:87:5 | a | 'a -> a -> 1 -^ ... + ... -^ ... = ...' | -| 90 | cfg.swift:90:3:92:3 | func addOptional | 'func addOptional' | +| 90 | cfg.swift:90:3:92:3 | func addOptional | 'func addOptional -V addOptional' | | 90 | cfg.swift:90:20:90:20 | a | 'a -> Block' | | 91 | cfg.swift:91:5:91:5 | a | 'a -> nil -^ ... = ...' | | 94 | cfg.swift:94:3:94:5 | add | 'add -> Argument -V temp -^ & ... -^ add(...)' | @@ -86,10 +86,10 @@ | 102 | cfg.swift:102:3:104:3 | init | 'init' | | 102 | cfg.swift:102:8:102:8 | n | 'n -> Block' | | 103 | cfg.swift:103:5:103:9 | myInt | 'myInt -> n -^ ... = ...' | -| 106 | cfg.swift:106:3:108:3 | func getMyInt | 'func getMyInt' | +| 106 | cfg.swift:106:3:108:3 | func getMyInt | 'func getMyInt -V getMyInt' | | 106 | cfg.swift:106:26:108:3 | Block | 'Block' | | 107 | cfg.swift:107:12:107:16 | myInt | 'myInt -^ ReturnExpr' | -| 111 | cfg.swift:111:1:137:1 | func testMemberRef | 'func testMemberRef' | +| 111 | cfg.swift:111:1:137:1 | func testMemberRef | 'func testMemberRef -V testMemberRef' | | 111 | cfg.swift:111:20:111:24 | param | 'param -> inoutParam -> opt -> Block' | | 112 | cfg.swift:112:3:112:18 | let c | 'let c -V c -> C -> Argument -V 42 -^ C(...)' | | 113 | cfg.swift:113:3:113:18 | let n1 | 'let n1 -V n1 -> c -^ ... .myInt' | @@ -112,7 +112,7 @@ | 134 | cfg.swift:134:3:134:27 | let n18 | 'let n18 -V n18 -> opt -^ ... .self -^ ... .myInt' | | 135 | cfg.swift:135:3:135:27 | let n19 | 'let n19 -V n19 -> opt -^ ... .getMyInt -^ ... .getMyInt(...)' | | 136 | cfg.swift:136:3:136:32 | let n20 | 'let n20 -V n20 -> opt -^ ... .self -^ ... .getMyInt -^ ... .getMyInt(...)' | -| 139 | cfg.swift:139:1:166:1 | func patterns | 'func patterns' | +| 139 | cfg.swift:139:1:166:1 | func patterns | 'func patterns -V patterns' | | 139 | cfg.swift:139:15:139:15 | x | 'x -> Block' | | 140 | cfg.swift:140:3:141:12 | ForEachStmt | 'ForEachStmt -V 0 -> 10 -^ ... ... ...' | | 140 | cfg.swift:140:7:140:7 | _ | '_' | @@ -127,7 +127,7 @@ | 150 | cfg.swift:150:7:150:17 | Block | 'Block -V true -^ ReturnExpr' | | 151 | cfg.swift:151:5:152:18 | SwitchCase | 'SwitchCase' | | 152 | cfg.swift:152:7:152:18 | Block | 'Block -V false -^ ReturnExpr' | -| 168 | cfg.swift:168:1:184:1 | func testDefer | 'func testDefer' | +| 168 | cfg.swift:168:1:184:1 | func testDefer | 'func testDefer -V testDefer' | | 168 | cfg.swift:168:16:168:16 | x | 'x -> Block' | | 170 | cfg.swift:170:3:172:3 | DeferStmt | 'DeferStmt -V Block' | | 171 | cfg.swift:171:5:171:9 | print | 'print -> Argument -V "4" -^ print(...)' | @@ -137,7 +137,7 @@ | 179 | cfg.swift:179:5:179:9 | print | 'print -> Argument -V "1" -^ print(...)' | | 180 | cfg.swift:180:6:182:5 | DeferStmt | 'DeferStmt -V Block' | | 181 | cfg.swift:181:7:181:11 | print | 'print -> Argument -V "2" -^ print(...)' | -| 186 | cfg.swift:186:1:198:1 | func m1 | 'func m1' | +| 186 | cfg.swift:186:1:198:1 | func m1 | 'func m1 -V m1' | | 186 | cfg.swift:186:9:186:9 | x | 'x -> Block' | | 187 | cfg.swift:187:3:197:3 | IfExpr | 'IfExpr -V x -> 2 -^ ... > ...' | | 187 | cfg.swift:187:12:189:3 | Block | 'Block' | @@ -149,13 +149,13 @@ | 193 | cfg.swift:193:5:193:9 | print | 'print -> Argument -V "x is 1" -^ print(...)' | | 195 | cfg.swift:195:8:197:3 | Block | 'Block' | | 196 | cfg.swift:196:5:196:9 | print | 'print -> Argument -V "I can't guess the number" -^ print(...)' | -| 200 | cfg.swift:200:1:205:1 | func m2 | 'func m2' | +| 200 | cfg.swift:200:1:205:1 | func m2 | 'func m2 -V m2' | | 200 | cfg.swift:200:9:200:9 | b | 'b -> Block' | | 201 | cfg.swift:201:3:203:3 | IfExpr | 'IfExpr -V b' | | 201 | cfg.swift:201:8:203:3 | Block | 'Block' | | 202 | cfg.swift:202:12:202:12 | 0 | '0 -^ ReturnExpr' | | 204 | cfg.swift:204:10:204:10 | 1 | '1 -^ ReturnExpr' | -| 207 | cfg.swift:207:1:215:1 | func m3 | 'func m3' | +| 207 | cfg.swift:207:1:215:1 | func m3 | 'func m3 -V m3' | | 207 | cfg.swift:207:9:207:9 | x | 'x -> Block' | | 208 | cfg.swift:208:3:213:3 | IfExpr | 'IfExpr -V x -> 0 -^ ... < ...' | | 208 | cfg.swift:208:12:213:3 | Block | 'Block' | @@ -164,7 +164,7 @@ | 210 | cfg.swift:210:15:212:5 | Block | 'Block' | | 211 | cfg.swift:211:7:211:7 | x | 'x -> x -> 1 -^ ... - ... -^ ... = ...' | | 214 | cfg.swift:214:10:214:10 | x | 'x -^ ReturnExpr' | -| 217 | cfg.swift:217:1:223:1 | func m4 | 'func m4' | +| 217 | cfg.swift:217:1:223:1 | func m4 | 'func m4 -V m4' | | 217 | cfg.swift:217:10:217:11 | b1 | 'b1 -> b2 -> b3 -> Block' | | 218 | cfg.swift:218:3:222:20 | ReturnExpr | 'ReturnExpr' | | 218 | cfg.swift:218:10:222:20 | IfExpr | 'IfExpr -V IfExpr -V b1' | @@ -172,7 +172,7 @@ | 220 | cfg.swift:220:13:220:14 | b3 | 'b3' | | 221 | cfg.swift:221:9:221:18 | "b2 \|\| b3" | '"b2 \|\| b3"' | | 222 | cfg.swift:222:9:222:20 | "!b2 \|\| !b3" | '"!b2 \|\| !b3"' | -| 225 | cfg.swift:225:1:234:1 | func conversionsInSplitEntry | 'func conversionsInSplitEntry' | +| 225 | cfg.swift:225:1:234:1 | func conversionsInSplitEntry | 'func conversionsInSplitEntry -V conversionsInSplitEntry' | | 225 | cfg.swift:225:31:225:31 | b | 'b -> Block' | | 226 | cfg.swift:226:3:233:3 | IfExpr | 'IfExpr -V IfExpr -V b' | | 227 | cfg.swift:227:8:227:11 | true | 'true' | @@ -181,23 +181,23 @@ | 229 | cfg.swift:229:12:229:14 | "b" | '"b" -^ ReturnExpr' | | 231 | cfg.swift:231:8:233:3 | Block | 'Block' | | 232 | cfg.swift:232:12:232:15 | "!b" | '"!b" -^ ReturnExpr' | -| 236 | cfg.swift:236:1:240:1 | func constant_condition | 'func constant_condition' | +| 236 | cfg.swift:236:1:240:1 | func constant_condition | 'func constant_condition -V constant_condition' | | 236 | cfg.swift:236:27:240:1 | Block | 'Block' | | 237 | cfg.swift:237:3:239:3 | IfExpr | 'IfExpr -V ! ... -V true' | -| 242 | cfg.swift:242:1:248:1 | func empty_else | 'func empty_else' | +| 242 | cfg.swift:242:1:248:1 | func empty_else | 'func empty_else -V empty_else' | | 242 | cfg.swift:242:17:242:17 | b | 'b -> Block' | | 243 | cfg.swift:243:3:246:9 | IfExpr | 'IfExpr -V b' | | 243 | cfg.swift:243:8:245:3 | Block | 'Block' | | 244 | cfg.swift:244:5:244:9 | print | 'print -> Argument -V "true" -^ print(...)' | | 246 | cfg.swift:246:8:246:9 | Block | 'Block' | | 247 | cfg.swift:247:3:247:7 | print | 'print -> Argument -V "done" -^ print(...)' | -| 250 | cfg.swift:250:1:254:1 | func disjunct | 'func disjunct' | +| 250 | cfg.swift:250:1:254:1 | func disjunct | 'func disjunct -V disjunct' | | 250 | cfg.swift:250:16:250:17 | b1 | 'b1 -> b2 -> Block' | | 251 | cfg.swift:251:3:253:3 | IfExpr | 'IfExpr -V ... \|\| ... -V b1' | | 251 | cfg.swift:251:13:251:14 | b2 | 'b2' | | 251 | cfg.swift:251:17:253:3 | Block | 'Block' | | 252 | cfg.swift:252:5:252:9 | print | 'print -> Argument -V "b1 or b2" -^ print(...)' | -| 256 | cfg.swift:256:1:273:1 | func binaryExprs | 'func binaryExprs' | +| 256 | cfg.swift:256:1:273:1 | func binaryExprs | 'func binaryExprs -V binaryExprs' | | 256 | cfg.swift:256:18:256:18 | a | 'a -> b -> Block' | | 257 | cfg.swift:257:3:257:15 | let c | 'let c -V c -> a -> b -^ ... + ...' | | 258 | cfg.swift:258:3:258:15 | let d | 'let d -V d -> a -> b -^ ... - ...' | @@ -215,10 +215,10 @@ | 270 | cfg.swift:270:3:270:16 | let r | 'let r -V r -> a -> b -^ ... <= ...' | | 271 | cfg.swift:271:3:271:15 | let s | 'let s -V s -> a -> b -^ ... > ...' | | 272 | cfg.swift:272:3:272:16 | let t | 'let t -V t -> a -> b -^ ... >= ...' | -| 275 | cfg.swift:275:1:277:1 | func interpolatedString | 'func interpolatedString' | +| 275 | cfg.swift:275:1:277:1 | func interpolatedString | 'func interpolatedString -V interpolatedString' | | 275 | cfg.swift:275:25:275:25 | x | 'x -> y -> Block' | | 276 | cfg.swift:276:11:276:10 | | ' -> interpolation -> Argument -V x -^ interpolation(...) -> + -> interpolation -> Argument -V y -^ interpolation(...) -> is equal to -> interpolation -> Argument -V x -> y -^ ... + ... -^ interpolation(...) -> and here is a zero: -> interpolation -> Argument -V returnZero -^ returnZero(...) -^ interpolation(...) -> -^ StringInterpolationExpr -^ ReturnExpr' | -| 279 | cfg.swift:279:1:310:1 | func testSubscriptExpr | 'func testSubscriptExpr' | +| 279 | cfg.swift:279:1:310:1 | func testSubscriptExpr | 'func testSubscriptExpr -V testSubscriptExpr' | | 279 | cfg.swift:279:55:310:1 | Block | 'Block' | | 280 | cfg.swift:280:3:280:44 | var a | 'var a -V a -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -^ ArrayLiteral' | | 281 | cfg.swift:281:3:281:3 | a | 'a -> Argument -V 0 -^ a(...) -> 0 -^ ... = ...' | @@ -247,14 +247,14 @@ | 306 | cfg.swift:306:3:306:3 | b | 'b -> Argument -V 10 -^ b(...) -> b -> Argument -V 9 -^ b(...) -> 1 -^ ... >> ... -^ ... = ...' | | 308 | cfg.swift:308:3:308:39 | let | 'let -V Argument -V a1 -> Argument -V a2 -> Argument -V a3 -> Argument -V a4 -> Argument -V a5 -^ TupleExpr -> tupleWithA' | | 309 | cfg.swift:309:11:309:19 | Argument | 'Argument -V a1 -> b -> Argument -V 0 -^ b(...) -^ ... + ... -> Argument -V a2 -> b -> Argument -V 1 -^ b(...) -^ ... + ... -> Argument -V a3 -> b -> Argument -V 2 -^ b(...) -^ ... + ... -> Argument -V a4 -> b -> Argument -V 3 -^ b(...) -^ ... + ... -> Argument -V a5 -> b -> Argument -V 4 -^ b(...) -^ ... + ... -^ TupleExpr -^ ReturnExpr' | -| 312 | cfg.swift:312:1:317:1 | func loop1 | 'func loop1' | +| 312 | cfg.swift:312:1:317:1 | func loop1 | 'func loop1 -V loop1' | | 312 | cfg.swift:312:12:312:12 | x | 'x -> Block' | | 313 | cfg.swift:313:3:316:3 | WhileStmt | 'WhileStmt' | | 313 | cfg.swift:313:9:313:9 | x | 'x -> 0 -^ ... >= ...' | | 313 | cfg.swift:313:16:316:3 | Block | 'Block' | | 314 | cfg.swift:314:5:314:9 | print | 'print -> Argument -V x -^ print(...)' | | 315 | cfg.swift:315:5:315:5 | x | 'x -> 1 -^ ... -= ...' | -| 319 | cfg.swift:319:1:332:1 | func loop2 | 'func loop2' | +| 319 | cfg.swift:319:1:332:1 | func loop2 | 'func loop2 -V loop2' | | 319 | cfg.swift:319:12:319:12 | x | 'x -> Block' | | 320 | cfg.swift:320:3:330:3 | WhileStmt | 'WhileStmt' | | 320 | cfg.swift:320:9:320:9 | x | 'x -> 0 -^ ... >= ...' | @@ -269,7 +269,7 @@ | 327 | cfg.swift:327:7:327:14 | ContinueExpr | 'ContinueExpr' | | 329 | cfg.swift:329:5:329:9 | print | 'print -> Argument -V "Iter" -^ print(...)' | | 331 | cfg.swift:331:3:331:7 | print | 'print -> Argument -V "Done" -^ print(...)' | -| 334 | cfg.swift:334:1:349:1 | func labeledLoop | 'func labeledLoop' | +| 334 | cfg.swift:334:1:349:1 | func labeledLoop | 'func labeledLoop -V labeledLoop' | | 334 | cfg.swift:334:18:334:18 | x | 'x -> Block' | | 335 | cfg.swift:335:3:348:3 | LabeledStmt | 'LabeledStmt -V WhileStmt' | | 335 | cfg.swift:335:16:335:16 | x | 'x -> 0 -^ ... >= ...' | @@ -287,14 +287,14 @@ | 343 | cfg.swift:343:9:343:22 | ContinueExpr | 'ContinueExpr' | | 345 | cfg.swift:345:7:345:11 | print | 'print -> Argument -V "Iter" -^ print(...)' | | 347 | cfg.swift:347:5:347:9 | print | 'print -> Argument -V "Done" -^ print(...)' | -| 351 | cfg.swift:351:1:356:1 | func testRepeat | 'func testRepeat' | +| 351 | cfg.swift:351:1:356:1 | func testRepeat | 'func testRepeat -V testRepeat' | | 351 | cfg.swift:351:17:351:17 | x | 'x -> Block' | | 352 | cfg.swift:352:3:355:16 | DoWhileStmt | 'DoWhileStmt' | | 352 | cfg.swift:352:10:355:3 | Block | 'Block' | | 353 | cfg.swift:353:5:353:9 | print | 'print -> Argument -V x -^ print(...)' | | 354 | cfg.swift:354:5:354:5 | x | 'x -> 1 -^ ... -= ...' | | 355 | cfg.swift:355:11:355:11 | x | 'x -> 0 -^ ... >= ...' | -| 358 | cfg.swift:358:1:363:1 | func loop_with_identity_expr | 'func loop_with_identity_expr' | +| 358 | cfg.swift:358:1:363:1 | func loop_with_identity_expr | 'func loop_with_identity_expr -V loop_with_identity_expr' | | 358 | cfg.swift:358:32:363:1 | Block | 'Block' | | 359 | cfg.swift:359:3:359:11 | var x | 'var x -V x -> 0' | | 360 | cfg.swift:360:3:362:3 | WhileStmt | 'WhileStmt' | @@ -306,24 +306,24 @@ | 367 | cfg.swift:367:3:369:3 | init | 'init' | | 367 | cfg.swift:367:8:367:10 | arg | 'arg -> Block' | | 368 | cfg.swift:368:5:368:5 | c | 'c -> arg -^ ... = ...' | -| 371 | cfg.swift:371:3:373:3 | func getOptional | 'func getOptional' | +| 371 | cfg.swift:371:3:373:3 | func getOptional | 'func getOptional -V getOptional' | | 371 | cfg.swift:371:28:373:3 | Block | 'Block' | | 372 | cfg.swift:372:12:372:12 | c | 'c -^ ReturnExpr' | -| 376 | cfg.swift:376:1:378:1 | func testOptional | 'func testOptional' | +| 376 | cfg.swift:376:1:378:1 | func testOptional | 'func testOptional -V testOptional' | | 376 | cfg.swift:376:19:376:19 | c | 'c -> Block' | | 377 | cfg.swift:377:10:377:10 | c | 'c -^ ... .getOptional -^ ... .getOptional(...) -^ ... .getMyInt -^ ... .getMyInt(...) -^ ReturnExpr' | -| 380 | cfg.swift:380:1:384:1 | func testCapture | 'func testCapture' | +| 380 | cfg.swift:380:1:384:1 | func testCapture | 'func testCapture -V testCapture' | | 380 | cfg.swift:380:18:380:18 | x | 'x -> y -> Block' | | 381 | cfg.swift:381:13:381:21 | z | 'z -V z -> x -> y -^ ... + ... -> t -V t -> "literal" -^ FunctionExpr -^ ReturnExpr' | | 382 | cfg.swift:382:5:382:12 | Block | 'Block -V z -^ ReturnExpr' | -| 386 | cfg.swift:386:1:388:1 | func testTupleElement | 'func testTupleElement' | +| 386 | cfg.swift:386:1:388:1 | func testTupleElement | 'func testTupleElement -V testTupleElement' | | 386 | cfg.swift:386:23:386:23 | t | 't -> Block' | | 387 | cfg.swift:387:10:387:10 | t | 't -^ ... .a -> t -^ ... .1 -^ ... + ... -> t -^ ... .c -^ ... + ... -> Argument -V 1 -> Argument -V 2 -> Argument -V 3 -^ TupleExpr -^ ... .0 -^ ... + ... -^ ReturnExpr' | | 390 | cfg.swift:390:1:394:1 | class Derived | 'class Derived -V Derived -> BaseType -V C' | | 391 | cfg.swift:391:3:393:3 | init | 'init' | | 391 | cfg.swift:391:10:393:3 | Block | 'Block' | | 392 | cfg.swift:392:5:392:9 | super | 'super -^ ... .init -> Argument -V 0 -^ ... .init(...)' | -| 396 | cfg.swift:396:1:404:1 | func doWithoutCatch | 'func doWithoutCatch' | +| 396 | cfg.swift:396:1:404:1 | func doWithoutCatch | 'func doWithoutCatch -V doWithoutCatch' | | 396 | cfg.swift:396:21:396:21 | x | 'x -> Block' | | 397 | cfg.swift:397:3:402:3 | TryExpr | 'TryExpr -V Block' | | 398 | cfg.swift:398:5:398:24 | try ... | 'try ...' | @@ -340,10 +340,10 @@ | 412 | cfg.swift:412:3:414:3 | DestructorDeclaration | 'DestructorDeclaration' | | 412 | cfg.swift:412:10:414:3 | Block | 'Block' | | 413 | cfg.swift:413:5:413:9 | field | 'field -> 0 -^ ... = ...' | -| 417 | cfg.swift:417:1:419:1 | func dictionaryLiteral | 'func dictionaryLiteral' | +| 417 | cfg.swift:417:1:419:1 | func dictionaryLiteral | 'func dictionaryLiteral -V dictionaryLiteral' | | 417 | cfg.swift:417:24:417:24 | x | 'x -> y -> Block' | | 418 | cfg.swift:418:11:418:13 | "x" | '"x" -> x -^ KeyValuePair -> "y" -> y -^ KeyValuePair -^ MapLiteral -^ ReturnExpr' | -| 421 | cfg.swift:421:1:444:1 | func localDeclarations | 'func localDeclarations' | +| 421 | cfg.swift:421:1:444:1 | func localDeclarations | 'func localDeclarations -V localDeclarations' | | 421 | cfg.swift:421:33:444:1 | Block | 'Block' | | 422 | cfg.swift:422:3:427:3 | class MyLocalClass | 'class MyLocalClass -V MyLocalClass' | | 423 | cfg.swift:423:5:423:14 | var x | 'var x -V x -> Int' | @@ -366,7 +366,7 @@ | 451 | cfg.swift:451:3:451:11 | var b | 'var b -V b -> B' | | 452 | cfg.swift:452:3:452:14 | var bs | 'var bs -V bs -> Array -> B -^ GenericTypeExpr' | | 453 | cfg.swift:453:3:453:15 | var mayB | 'var mayB -V mayB -> Optional -> B -^ GenericTypeExpr' | -| 456 | cfg.swift:456:1:466:1 | func test | 'func test' | +| 456 | cfg.swift:456:1:466:1 | func test | 'func test -V test' | | 456 | cfg.swift:456:11:456:11 | a | 'a -> Block' | | 457 | cfg.swift:457:3:457:24 | var kpGet_b_x | 'var kpGet_b_x -V kpGet_b_x -> ' | | 458 | cfg.swift:458:3:458:31 | var kpGet_bs_0_x | 'var kpGet_bs_0_x -V kpGet_bs_0_x -> ' | @@ -376,7 +376,7 @@ | 463 | cfg.swift:463:3:463:51 | var apply_kpGet_bs_0_x | 'var apply_kpGet_bs_0_x -V apply_kpGet_bs_0_x -> a -> Argument -V kpGet_bs_0_x -^ a(...)' | | 464 | cfg.swift:464:3:464:63 | var apply_kpGet_mayB_force_x | 'var apply_kpGet_mayB_force_x -V apply_kpGet_mayB_force_x -> a -> Argument -V kpGet_mayB_force_x -^ a(...)' | | 465 | cfg.swift:465:3:465:51 | var apply_kpGet_mayB_x | 'var apply_kpGet_mayB_x -V apply_kpGet_mayB_x -> a -> Argument -V kpGet_mayB_x -^ a(...)' | -| 468 | cfg.swift:468:1:495:1 | func testIfConfig | 'func testIfConfig' | +| 468 | cfg.swift:468:1:495:1 | func testIfConfig | 'func testIfConfig -V testIfConfig' | | 468 | cfg.swift:468:21:495:1 | Block | 'Block' | | 469 | cfg.swift:469:1:475:6 | | '' | | 477 | cfg.swift:477:3:477:3 | 5 | '5' | @@ -384,7 +384,7 @@ | 484 | cfg.swift:484:3:484:3 | 8 | '8' | | 486 | cfg.swift:486:1:492:6 | | '' | | 494 | cfg.swift:494:3:494:4 | 13 | '13' | -| 497 | cfg.swift:497:1:522:1 | func testAvailable | 'func testAvailable' | +| 497 | cfg.swift:497:1:522:1 | func testAvailable | 'func testAvailable -V testAvailable' | | 497 | cfg.swift:497:29:522:1 | Block | 'Block' | | 498 | cfg.swift:498:3:498:11 | var x | 'var x -V x -> 0' | | 500 | cfg.swift:500:3:502:3 | IfExpr | 'IfExpr -V ' | @@ -404,7 +404,7 @@ | 517 | cfg.swift:517:29:519:3 | Block | 'Block' | | 518 | cfg.swift:518:5:518:5 | x | 'x -> 1 -^ ... += ...' | | 521 | cfg.swift:521:10:521:10 | x | 'x -^ ReturnExpr' | -| 524 | cfg.swift:524:1:538:1 | func testAsyncFor | 'func testAsyncFor' | +| 524 | cfg.swift:524:1:538:1 | func testAsyncFor | 'func testAsyncFor -V testAsyncFor' | | 524 | cfg.swift:524:28:538:1 | Block | 'Block' | | 525 | cfg.swift:525:5:533:6 | var stream | 'var stream -V stream -> AsyncStream -> Argument -V Int -^ ... .self -> Argument -V . -^ ... .bufferingNewest -> Argument -V 5 -^ ... .bufferingNewest(...) -> Argument -V FunctionExpr -^ AsyncStream(...)' | | 526 | cfg.swift:526:9:526:20 | continuation | 'continuation' | @@ -416,12 +416,12 @@ | 535 | cfg.swift:535:5:537:5 | ForEachStmt | 'ForEachStmt -V stream' | | 535 | cfg.swift:535:19:535:19 | i | 'i -> Block' | | 536 | cfg.swift:536:9:536:13 | print | 'print -> Argument -V i -^ print(...)' | -| 540 | cfg.swift:540:1:544:1 | func testNilCoalescing | 'func testNilCoalescing' | +| 540 | cfg.swift:540:1:544:1 | func testNilCoalescing | 'func testNilCoalescing -V testNilCoalescing' | | 540 | cfg.swift:540:24:540:24 | x | 'x -> Block' | | 541 | cfg.swift:541:3:543:9 | ReturnExpr | 'ReturnExpr' | | 542 | cfg.swift:542:5:543:9 | ... ?? ... | '... ?? ... -V x' | | 543 | cfg.swift:543:9:543:9 | 0 | '0' | -| 546 | cfg.swift:546:1:553:1 | func testNilCoalescing2 | 'func testNilCoalescing2' | +| 546 | cfg.swift:546:1:553:1 | func testNilCoalescing2 | 'func testNilCoalescing2 -V testNilCoalescing2' | | 546 | cfg.swift:546:25:546:25 | x | 'x -> Block' | | 547 | cfg.swift:547:3:552:3 | IfExpr | 'IfExpr -V ... ?? ... -V x' | | 548 | cfg.swift:548:7:548:11 | false | 'false' | @@ -429,31 +429,31 @@ | 549 | cfg.swift:549:12:549:12 | 1 | '1 -^ ReturnExpr' | | 550 | cfg.swift:550:10:552:3 | Block | 'Block' | | 551 | cfg.swift:551:12:551:12 | 0 | '0 -^ ReturnExpr' | -| 555 | cfg.swift:555:1:557:1 | func usesAutoclosure | 'func usesAutoclosure' | +| 555 | cfg.swift:555:1:557:1 | func usesAutoclosure | 'func usesAutoclosure -V usesAutoclosure' | | 555 | cfg.swift:555:24:555:27 | expr | 'expr -> Block' | | 556 | cfg.swift:556:10:556:13 | expr | 'expr -^ expr(...) -^ ReturnExpr' | -| 559 | cfg.swift:559:1:561:1 | func autoclosureTest | 'func autoclosureTest' | +| 559 | cfg.swift:559:1:561:1 | func autoclosureTest | 'func autoclosureTest -V autoclosureTest' | | 559 | cfg.swift:559:24:561:1 | Block | 'Block' | | 560 | cfg.swift:560:3:560:17 | usesAutoclosure | 'usesAutoclosure -> Argument -V 1 -^ usesAutoclosure(...)' | | 565 | cfg.swift:565:1:567:1 | protocol MyProtocol | 'protocol MyProtocol -V MyProtocol' | | 566 | cfg.swift:566:2:566:1 | Block | 'Block' | -| 566 | cfg.swift:566:2:566:21 | func source | 'func source' | +| 566 | cfg.swift:566:2:566:21 | func source | 'func source -V source' | | 569 | cfg.swift:569:1:571:1 | class MyProcotolImpl | 'class MyProcotolImpl -V MyProcotolImpl -> BaseType -V MyProtocol' | -| 570 | cfg.swift:570:2:570:34 | func source | 'func source' | +| 570 | cfg.swift:570:2:570:34 | func source | 'func source -V source' | | 570 | cfg.swift:570:23:570:34 | Block | 'Block -V 0 -^ ReturnExpr' | -| 573 | cfg.swift:573:1:573:62 | func getMyProtocol | 'func getMyProtocol' | +| 573 | cfg.swift:573:1:573:62 | func getMyProtocol | 'func getMyProtocol -V getMyProtocol' | | 573 | cfg.swift:573:36:573:62 | Block | 'Block -V MyProcotolImpl -^ MyProcotolImpl(...) -^ ReturnExpr' | -| 574 | cfg.swift:574:1:574:70 | func getMyProtocolImpl | 'func getMyProtocolImpl' | +| 574 | cfg.swift:574:1:574:70 | func getMyProtocolImpl | 'func getMyProtocolImpl -V getMyProtocolImpl' | | 574 | cfg.swift:574:44:574:70 | Block | 'Block -V MyProcotolImpl -^ MyProcotolImpl(...) -^ ReturnExpr' | -| 576 | cfg.swift:576:1:576:23 | func sink | 'func sink' | +| 576 | cfg.swift:576:1:576:23 | func sink | 'func sink -V sink' | | 576 | cfg.swift:576:11:576:13 | arg | 'arg -> Block' | -| 578 | cfg.swift:578:1:583:1 | func testOpenExistentialExpr | 'func testOpenExistentialExpr' | +| 578 | cfg.swift:578:1:583:1 | func testOpenExistentialExpr | 'func testOpenExistentialExpr -V testOpenExistentialExpr' | | 578 | cfg.swift:578:30:578:30 | x | 'x -> y -> Block' | | 579 | cfg.swift:579:2:579:5 | sink | 'sink -> Argument -V x -^ ... .source -^ ... .source(...) -^ sink(...)' | | 580 | cfg.swift:580:2:580:5 | sink | 'sink -> Argument -V y -^ ... .source -^ ... .source(...) -^ sink(...)' | | 581 | cfg.swift:581:2:581:5 | sink | 'sink -> Argument -V getMyProtocol -^ getMyProtocol(...) -^ ... .source -^ ... .source(...) -^ sink(...)' | | 582 | cfg.swift:582:2:582:5 | sink | 'sink -> Argument -V getMyProtocolImpl -^ getMyProtocolImpl(...) -^ ... .source -^ ... .source(...) -^ sink(...)' | -| 585 | cfg.swift:585:1:593:1 | func singleStmtExpr | 'func singleStmtExpr' | +| 585 | cfg.swift:585:1:593:1 | func singleStmtExpr | 'func singleStmtExpr -V singleStmtExpr' | | 585 | cfg.swift:585:23:585:23 | x | 'x -> Block' | | 586 | cfg.swift:586:3:589:3 | let a | 'let a -V a -> SwitchExpr -V x' | | 587 | cfg.swift:587:5:587:17 | SwitchCase | 'SwitchCase -V 0 -> 5 -^ ... ..< ...' | @@ -465,7 +465,7 @@ | 592 | cfg.swift:592:14:592:18 | Block | 'Block -V 2' | | 596 | cfg.swift:596:1:598:1 | struct ValueGenericsStruct | 'struct ValueGenericsStruct -V ValueGenericsStruct -> TypeParameter -V N -> Int' | | 597 | cfg.swift:597:5:597:13 | var x | 'var x -V x -> N' | -| 600 | cfg.swift:600:1:604:1 | func valueGenericsFn | 'func valueGenericsFn' | +| 600 | cfg.swift:600:1:604:1 | func valueGenericsFn | 'func valueGenericsFn -V valueGenericsFn' | | 600 | cfg.swift:600:36:600:40 | value | 'value -> Block' | | 601 | cfg.swift:601:5:601:13 | var x | 'var x -V x -> N' | | 602 | cfg.swift:602:5:602:9 | print | 'print -> Argument -V x -^ print(...)' | diff --git a/unified/ql/test/library-tests/controlflow/cfg.expected b/unified/ql/test/library-tests/controlflow/cfg.expected index 9ce119975f36..52ba36cd4454 100644 --- a/unified/ql/test/library-tests/controlflow/cfg.expected +++ b/unified/ql/test/library-tests/controlflow/cfg.expected @@ -131,10 +131,9 @@ noCfg | cfg.swift:47:42:47:47 | String | | cfg.swift:53:34:53:34 | _ | | cfg.swift:60:34:60:34 | _ | -| cfg.swift:66:6:66:17 | callClosures | -| cfg.swift:77:6:77:27 | forceAndBackToOptional | -| cfg.swift:83:6:83:14 | testInOut | -| cfg.swift:106:8:106:15 | getMyInt | +| cfg.swift:77:34:77:33 | Optional | +| cfg.swift:83:21:83:23 | Int | +| cfg.swift:106:22:106:24 | Int | | cfg.swift:146:7:146:17 | ReturnExpr | | cfg.swift:155:3:155:5 | var | | cfg.swift:156:6:156:8 | obj | @@ -143,21 +142,16 @@ noCfg | cfg.swift:161:6:161:34 | PatternGuardExpr | | cfg.swift:162:5:162:17 | ReturnExpr | | cfg.swift:164:5:164:16 | ReturnExpr | -| cfg.swift:236:6:236:23 | constant_condition | | cfg.swift:238:5:238:9 | print | -| cfg.swift:279:6:279:22 | testSubscriptExpr | -| cfg.swift:358:6:358:28 | loop_with_identity_expr | -| cfg.swift:371:8:371:18 | getOptional | +| cfg.swift:279:29:279:53 | TupleExpr | +| cfg.swift:371:25:371:24 | Optional | | cfg.swift:380:45:380:47 | Int | | cfg.swift:391:3:391:6 | init | | cfg.swift:408:3:408:6 | init | -| cfg.swift:421:6:421:22 | localDeclarations | +| cfg.swift:421:29:421:31 | Int | | cfg.swift:424:5:424:8 | init | | cfg.swift:431:5:431:8 | init | -| cfg.swift:468:6:468:17 | testIfConfig | -| cfg.swift:497:6:497:18 | testAvailable | -| cfg.swift:524:6:524:17 | testAsyncFor | -| cfg.swift:559:6:559:20 | autoclosureTest | +| cfg.swift:497:25:497:27 | Int | nonSimple | cfg.swift:12:17:12:25 | withParam | 'withParam -? Block' | | cfg.swift:35:5:35:5 | CatchClause | 'CatchClause -V MyError -^ ... .error1 -> isZero -> Argument -V x -^ isZero(...) -? MyError -^ ... .error2 -^ ConditionalPattern -^ OrPattern' | diff --git a/unified/ql/test/library-tests/controlflow/cfg.swift b/unified/ql/test/library-tests/controlflow/cfg.swift index 276064a962f6..14c231837044 100644 --- a/unified/ql/test/library-tests/controlflow/cfg.swift +++ b/unified/ql/test/library-tests/controlflow/cfg.swift @@ -63,7 +63,7 @@ func createClosure3(x : Int) -> (_ : Int) -> Int { // $ noCfg } } -func callClosures() { // $ noCfg +func callClosures() { var x1 = createClosure1(s: "")() var x2 = createClosure2(x: 0)(10) var x3 = createClosure3(x: 0)(10) @@ -233,7 +233,7 @@ func conversionsInSplitEntry (b : Bool) -> String { } } -func constant_condition() { // $ noCfg +func constant_condition() { if !true { print("Impossible") // $ noCfg } @@ -355,7 +355,7 @@ func testRepeat(x : inout Int) { } while x >= 0 // $ bbStep='... >= ... : true -> Block(-3)' } -func loop_with_identity_expr() { // $ noCfg +func loop_with_identity_expr() { var x = 0 while(x < 10) { // $ bbStep='WhileStmt : successor -> x(+0)' bbStep='... < ... : true -> Block(+0)' x += 1 // $ bbStep='... += ... : successor -> x(-1)' @@ -465,7 +465,7 @@ func test(a : A) { var apply_kpGet_mayB_x = a[keyPath: kpGet_mayB_x] } -func testIfConfig() { // $ noCfg +func testIfConfig() { #if FOO 1 2 @@ -521,7 +521,7 @@ func testAvailable() -> Int { // $ noCfg return x } -func testAsyncFor () async { // $ noCfg +func testAsyncFor () async { var stream = AsyncStream(Int.self, bufferingPolicy: .bufferingNewest(5), { continuation in Task.detached { @@ -556,7 +556,7 @@ func usesAutoclosure(_ expr: @autoclosure () -> Int) -> Int { return expr() } -func autoclosureTest() { // $ noCfg +func autoclosureTest() { usesAutoclosure(1) } diff --git a/unified/ql/test/library-tests/local-name-binding/test.swift b/unified/ql/test/library-tests/local-name-binding/test.swift index 02558d808d4e..6de3cab47e3a 100644 --- a/unified/ql/test/library-tests/local-name-binding/test.swift +++ b/unified/ql/test/library-tests/local-name-binding/test.swift @@ -181,7 +181,7 @@ func t21() { // Nested functions func t22() { let x = 1 // name=x1 - func inner() { // $ captured=inner1 // name=inner1 + func inner() { // name=inner1 let x = 2 // name=x2 print(x) // $ access=x2 } From c575e37bd0fa22bd67b3450b7ea814f78e7129c0 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Sep 2026 16:52:28 +0200 Subject: [PATCH 19/40] unified: Instantiate capture lib and enable consistency queries --- .../CaptureSsaConsistency.ql | 3 + .../unified/internal/dataflow/AllDataFlow.qll | 1 + .../unified/internal/dataflow/CaptureSsa.qll | 87 +++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 unified/ql/consistency-queries/CaptureSsaConsistency.ql create mode 100644 unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll diff --git a/unified/ql/consistency-queries/CaptureSsaConsistency.ql b/unified/ql/consistency-queries/CaptureSsaConsistency.ql new file mode 100644 index 000000000000..19f35b7371fb --- /dev/null +++ b/unified/ql/consistency-queries/CaptureSsaConsistency.ql @@ -0,0 +1,3 @@ +private import unified +private import codeql.unified.internal.dataflow.CaptureSsa +import CaptureSsaOutput::ConsistencyChecks diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll b/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll index c8847276c828..ee5851bbfe2e 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/AllDataFlow.qll @@ -1,6 +1,7 @@ /** Re-exports all the files in the internal dataflow folder (except DataFlowPublic). */ import CallGraph +import CaptureSsa import Content import DataFlowCall import DataFlowCallable diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll b/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll new file mode 100644 index 000000000000..1bc653dfb5eb --- /dev/null +++ b/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll @@ -0,0 +1,87 @@ +/** + * SSA for captured variables. + */ + +private import unified +private import unified as U +private import AllDataFlow +private import codeql.dataflow.VariableCapture +private import codeql.unified.internal.ControlFlowGraph +private import codeql.unified.internal.ExprPositions + +module CaptureSsaInput implements InputSig { + final private class FinalCallable = U::Callable; + + class Callable extends FinalCallable { + Callable() { this.fromSource() } + + predicate isConstructor() { none() } // TODO + } + + Callable basicBlockGetEnclosingCallable(BasicBlock bb) { result = bb.getEnclosingCallable() } + + class CapturedVariable extends LocalVariable { + CapturedVariable() { this.isCaptured() } + + Callable getCallable() { result = super.getDeclaringCallable() } + } + + class CapturedParameter extends CapturedVariable { + // This class is not needed. Variables aren't the first point of contact with parameter values. + CapturedParameter() { none() } + } + + private class TExpr = TCallableNode or TLocalVariableRefNode; + + private predicate isTopLevelCallable(BuilderNode callable) { + callable.isCallable(any(TopLevel t)) + } + + class Expr extends TExpr { + Expr() { not isTopLevelCallable(this) } + + string toString() { result = this.(Node).toString() } + + Location getLocation() { result = this.(Node).getLocation() } + + predicate hasCfgNode(BasicBlock bb, int i) { + this.(LocalVariableRefNode).hasCfgNode(bb, i) + or + exists(DataFlowCallable callable | + this = TCallableNode(callable) and + bb.getNode(i).injects(callable.asSourceCallable()) + ) + } + } + + final private class FinalLocalVariableRefNode = LocalVariableRefNode; + + class VariableWrite extends FinalLocalVariableRefNode { + VariableWrite() { + this.getRefKind().isWrite() and super.getVariable() instanceof CapturedVariable + } + + CapturedVariable getVariable() { result = super.getVariable() } + } + + class VariableRead extends Expr instanceof LocalVariableRefNode { + VariableRead() { + super.getVariable() instanceof CapturedVariable and + super.getRefKind().isRead() + } + + CapturedVariable getVariable() { result = super.getVariable() } + } + + class ClosureExpr extends Expr instanceof TCallableNode { + private Callable callable; + + ClosureExpr() { this.(BuilderNode).isCallable(callable) } + + predicate hasBody(Callable body) { callable = body } + + predicate hasAliasedAccess(Expr f) { this = f } // TODO + } +} + +module CaptureSsaOutput = Flow; From 234695ad5ba6c0af32ad63b9c5bc0f89a5af68ff Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Sep 2026 16:52:28 +0200 Subject: [PATCH 20/40] unified: Add Stage2Node --- .../internal/dataflow/DataFlowNode.qll | 43 ++++++++++++------- .../unified/internal/dataflow/LocalSsa.qll | 10 ++--- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll index 5722fb4b03a7..a069c0a3404c 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll @@ -90,6 +90,8 @@ class TDataFlowNodeStage1 = TValueNode or TStrictlyIncomingValue or TExprPostUpdateNode or TLocalVariableRefNode or TCallableNode or TReceiverParameterNode or TReceiverArgumentNode; +class TDataFlowNodeStage2 = TDataFlowNodeStage1 or TLocalSsaNode; + /** * A data-flow node used during construction of the local data flow graph. * @@ -275,6 +277,29 @@ class BuilderNode extends TDataFlowNodeStage1 { } } +/** A node in stage 2, which includes stage 1 and local SSA nodes. */ +class Stage2Node extends TDataFlowNodeStage2 { + /** Get a string representation of this element. */ + string toString() { + result = this.(BuilderNode).toString() + or + exists(LocalSsaDataFlowOutput::SsaNode node | + this = TLocalSsaNode(node) and + result = node.toString() + ) + } + + /** Gets the location of this data flow node. */ + Location getLocation() { + result = this.(BuilderNode).getLocation() + or + exists(LocalSsaDataFlowOutput::SsaNode node | + this = TLocalSsaNode(node) and + result = node.getLocation() + ) + } +} + class Node extends TDataFlowNode { /** Gets the expression represented by this node. */ Expr asExpr() { this = TValueNode(result) } @@ -338,24 +363,10 @@ class Node extends TDataFlowNode { AstNode getWrappedAstNode() { result = this.(BuilderNode).getWrappedAstNode() } /** Get a string representation of this element. */ - string toString() { - result = this.(BuilderNode).toString() - or - exists(LocalSsaDataFlowOutput::SsaNode node | - this = TLocalSsaNode(node) and - result = node.toString() - ) - } + string toString() { result = this.(Stage2Node).toString() } /** Gets the location of this data flow node. */ - Location getLocation() { - result = this.(BuilderNode).getLocation() - or - exists(LocalSsaDataFlowOutput::SsaNode node | - this = TLocalSsaNode(node) and - result = node.getLocation() - ) - } + Location getLocation() { result = this.(Stage2Node).getLocation() } /** Gets the data-flow callable containing this data flow node. */ DataFlowCallable getEnclosingCallableEx() { diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll b/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll index 4fccf5065fa0..2a92691a6347 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/LocalSsa.qll @@ -74,18 +74,18 @@ private predicate postUpdateReadNode(Ssa::Node node) { node.(Ssa::ExprNode).getExpr() = TLocalVariableRefNode(_, _, TPostUpdate()) } -Node getNodeFromLocalSsaNode(Ssa::Node n) { +Stage2Node getNodeFromLocalSsaNode(Ssa::Node n) { result = TLocalSsaNode(n) or result = n.(Ssa::ExprNode).getExpr() and not postUpdateReadNode(n) or - result = n.(Ssa::ExprPostUpdateNode).getExpr().(Node).getPostUpdateNode() + result = n.(Ssa::ExprPostUpdateNode).getExpr().(BuilderNode).getPostUpdateNode() or exists(LocalVariable v, BasicBlock bb, int i, AstNode repr | n.(Ssa::WriteDefSourceNode).getDefinition().definesAt(v, bb, i) and performsVariableAccess(repr, v, TWrite(), bb.getNode(i)) and - result.isLocalVariableWrite(repr, v) + result.(BuilderNode).isLocalVariableWrite(repr, v) ) } @@ -103,7 +103,7 @@ predicate skipPostUpdateRead(Ssa::Node node1, Ssa::Node node2) { ) } -predicate localSsaStep(Node node1, Node node2, boolean isUseStep) { +predicate localSsaStep(Stage2Node node1, Stage2Node node2, boolean isUseStep) { exists(Ssa::Node ssa1, Ssa::Node ssa2 | ( Ssa::localFlowStep(_, ssa1, ssa2, isUseStep) @@ -117,7 +117,7 @@ predicate localSsaStep(Node node1, Node node2, boolean isUseStep) { ) } -predicate localSsaMustFlowStep(Node node1, Node node2) { +predicate localSsaMustFlowStep(Stage2Node node1, Stage2Node node2) { exists(Ssa::Node ssa1, Ssa::Node ssa2 | Ssa::localMustFlowStep(_, ssa1, ssa2) and node1 = getNodeFromLocalSsaNode(ssa1) and From d02296c7e51714fc1dc70b19a1cc86dba5b5f2c1 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 29 Sep 2026 16:53:02 +0200 Subject: [PATCH 21/40] unified: Use local data flow for alias detection --- .../unified/internal/dataflow/CaptureSsa.qll | 28 ++++++++++++++++++- .../internal/dataflow/DataFlowGraph.qll | 12 ++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll b/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll index 1bc653dfb5eb..555d814277a0 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll @@ -73,6 +73,32 @@ module CaptureSsaInput implements InputSig { CapturedVariable getVariable() { result = super.getVariable() } } + /** + * Holds if `node` is a possible alias for `callable`. + */ + private predicate callableHasLocalAlias(Callable callable, Stage2Node node) { + node.(BuilderNode).isCallable(callable) + or + exists(Stage2Node prev | callableHasLocalAlias(callable, prev) | + step(prev, any(Step s | s.value()), node) + or + localSsaStep(prev, node, _) + ) + or + exists(CapturedVariable var | + callableHasLocalAliasVar(callable, var) and + node.(BuilderNode).isLocalVariableRead(_, var) + ) + } + + pragma[nomagic] + private predicate callableHasLocalAliasVar(Callable callable, CapturedVariable var) { + exists(BuilderNode ref | + callableHasLocalAlias(callable, ref) and + ref.isLocalVariableWrite(_, var) + ) + } + class ClosureExpr extends Expr instanceof TCallableNode { private Callable callable; @@ -80,7 +106,7 @@ module CaptureSsaInput implements InputSig { predicate hasBody(Callable body) { callable = body } - predicate hasAliasedAccess(Expr f) { this = f } // TODO + predicate hasAliasedAccess(Expr f) { callableHasLocalAlias(callable, f) } } } diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll index d38d7466a3b5..4d9f9c5e8b28 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll @@ -103,6 +103,18 @@ predicate step(BuilderNode node1, Step step, BuilderNode node2) { node2.isPostUpdate(expr.getBase()) ) or + exists(FunctionExpr expr | + node1.isCallable(expr) and + step.value() and + node2.isResultValue(expr) + ) + or + exists(FunctionDeclaration fun | + node1.isCallable(fun) and + step.value() and + node2.isIncomingValue(fun.getNameNode()) + ) + or none() // Temporarily disable compilation errors from unsatisfiable types } From 8b05e52a05096eeb7639cbb3aca4e8769c2200a1 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 09:07:15 +0200 Subject: [PATCH 22/40] unified: Add TCaptureSsaNode --- .../codeql/dataflow/VariableCapture.qll | 10 +++++ .../internal/dataflow/DataFlowNode.qll | 39 +++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/VariableCapture.qll b/shared/dataflow/codeql/dataflow/VariableCapture.qll index ab798b02cf2d..702e52e8e738 100644 --- a/shared/dataflow/codeql/dataflow/VariableCapture.qll +++ b/shared/dataflow/codeql/dataflow/VariableCapture.qll @@ -812,6 +812,16 @@ module Flow< or exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getSourceVariable() = TThis(_)) } + + predicate hasCfgNode(BasicBlock bb, int i) { + this = TSynthRead(_, bb, i, _) + or + this = TSynthThisQualifier(bb, i, _) + or + exists(SsaFlow::SsaNode n | + this = TSynthSsa(n) and n.getBasicBlock() = bb and n.getIndex() = i + ) + } } class ExprNode extends ClosureNode, TExprNode { diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll index a069c0a3404c..447284c4698d 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll @@ -84,7 +84,8 @@ newtype TDataFlowNode = TCallableNode(DataFlowCallable callable) or TReceiverParameterNode(DataFlowCallable callable) or TReceiverArgumentNode(DataFlowCall call, Boolean isPost) or - TLocalSsaNode(LocalSsaDataFlowOutput::SsaNode node) + TLocalSsaNode(LocalSsaDataFlowOutput::SsaNode node) or + TCaptureSsaNode(CaptureSsaOutput::SynthesizedCaptureNode node) class TDataFlowNodeStage1 = TValueNode or TStrictlyIncomingValue or TExprPostUpdateNode or TLocalVariableRefNode or @@ -363,10 +364,24 @@ class Node extends TDataFlowNode { AstNode getWrappedAstNode() { result = this.(BuilderNode).getWrappedAstNode() } /** Get a string representation of this element. */ - string toString() { result = this.(Stage2Node).toString() } + string toString() { + result = this.(Stage2Node).toString() + or + exists(CaptureSsaOutput::SynthesizedCaptureNode node | + this = TCaptureSsaNode(node) and + result = "[capture] " + node.toString() + ) + } /** Gets the location of this data flow node. */ - Location getLocation() { result = this.(Stage2Node).getLocation() } + Location getLocation() { + result = this.(Stage2Node).getLocation() + or + exists(CaptureSsaOutput::SynthesizedCaptureNode node | + this = TCaptureSsaNode(node) and + result = node.getLocation() + ) + } /** Gets the data-flow callable containing this data flow node. */ DataFlowCallable getEnclosingCallableEx() { @@ -385,6 +400,13 @@ class Node extends TDataFlowNode { or this.(BuilderNode).isReceiverParameterEx(result) or + exists(CaptureSsaOutput::SynthesizedCaptureNode node | + this = TCaptureSsaNode(node) and + result.asSourceCallable() = node.getEnclosingCallable() + ) + or + this.(BuilderNode).isImplicitParameter(result, _) + or exists(DataFlowCall call | this.(BuilderNode).isReceiverArgumentEx(call, _) and result = call.getEnclosingCallable() @@ -446,6 +468,11 @@ class Node extends TDataFlowNode { bb = node.getBasicBlock() and i = node.getIndex() // TODO: why is this marked as internal in the SSA library? ) + or + exists(CaptureSsaOutput::SynthesizedCaptureNode node | + this = TCaptureSsaNode(node) and + node.hasCfgNode(bb, i) + ) } /** Gets the basic block associated with this data flow node, if any. */ @@ -456,5 +483,9 @@ class Node extends TDataFlowNode { * * The post-update node represents the updated state of the value held in this node, after it has been mutated by the surrounding assignment or call. */ - Node getPostUpdateNode() { result = this.(BuilderNode).getPostUpdateNode() } + Node getPostUpdateNode() { + result = this.(BuilderNode).getPostUpdateNode() + or + result = getCaptureSsaPostUpdate(this) + } } From bbde984a2e628d44e056c91032429a3a87439c8c Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 09:25:36 +0200 Subject: [PATCH 23/40] unified: Add callee param/arg position --- .../unified/internal/dataflow/ParameterPositions.qll | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll b/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll index 4d7b1fa77102..e44d86484c2a 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll @@ -2,6 +2,7 @@ private import unified private newtype TParameterPosition = TReceiverParameter() or + TCalleeParameter() or TPositionalParameter(int n) { n = [0 .. 20] } or TNamedParameter(string name) { name = any(Parameter p).getExternalName() @@ -10,8 +11,12 @@ private newtype TParameterPosition = } class ParameterPosition extends TParameterPosition { + /** Holds if this represents the receiver passed to a call (usually called `this` or `self`). */ predicate isReceiver() { this = TReceiverParameter() } + /** Holds if this represents the function value being invoked in a call. */ + predicate isCallee() { this = TCalleeParameter() } + int asPositional() { this = TPositionalParameter(result) } string asNamed() { this = TNamedParameter(result) } @@ -19,6 +24,8 @@ class ParameterPosition extends TParameterPosition { string toString() { this.isReceiver() and result = "receiver" or + this.isCallee() and result = "callee" + or result = this.asPositional().toString() or // Suffix with a colon to prevent a confusing name clash with "receiver". This also aligns with MaD syntax. From 943be7721161441287c2d1581866fa6503c13219 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 13:57:13 +0200 Subject: [PATCH 24/40] unified: Callee always has a post-update Since the callee itself is now always considered to be an argument, it needs to have a post-update node. This only matters when the callee is a function with captures, but it should be harmless in general. --- .../ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll index 447284c4698d..aa5e0e8e9e6f 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll @@ -31,7 +31,7 @@ private predicate hasPostUpdate(Expr expr, ControlFlowNode cfgNode) { exists(CallExpr call | cfgNode.isAfter(call) | expr = call.getAnArgument().getValue() or - expr = call.getCallee().(MemberAccessExpr).getBase() + expr = call.getCallee() ) } From 924f1fb683371d2cf0d3677dbc249202ddd280c5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 09:58:52 +0200 Subject: [PATCH 25/40] unified: Generalize receiver nodes to implicit arg/param nodes --- .../internal/dataflow/DataFlowGraph.qll | 10 ++ .../dataflow/DataFlowInstantiation.qll | 6 +- .../internal/dataflow/DataFlowNode.qll | 94 ++++++++++--------- .../internal/dataflow/ParameterPositions.qll | 8 ++ 4 files changed, 68 insertions(+), 50 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll index 4d9f9c5e8b28..090b9f5f2902 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll @@ -23,6 +23,16 @@ predicate step(BuilderNode node1, Step step, BuilderNode node2) { node2.isPostUpdate(receiverExpr) ) or + exists(CallExpr call | + node1.isResultValue(call.getCallee()) and + step.value() and + node2.isCalleeArgument(call) + or + node1.isCalleePostUpdate(call) and + step.value() and + node2.isPostUpdate(call.getCallee()) + ) + or exists(CallExpr call, UnqualifiedMemberAccess callee | callee = call.getCallee() | node1.isLocalVariableRead(callee, callee.getImplicitQualifierVariable()) and step.value() and diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll index 0e2b28a8d7a3..a7c85c39a0f6 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll @@ -57,8 +57,7 @@ module DataFlowInput implements InputSig { pos.asNamed() = param.getExternalName() ) or - p.(BuilderNode).isReceiverParameterEx(c) and - pos.isReceiver() + p.(BuilderNode).isImplicitParameter(c, pos) } class ParameterNode extends Node { @@ -80,8 +79,7 @@ module DataFlowInput implements InputSig { pos.asNamed() = arg.getName() ) or - n.(BuilderNode).isReceiverArgumentEx(call) and - pos.isReceiver() + n.(BuilderNode).isImplicitArgument(call, pos, false) } class ArgumentNode extends Node { diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll index aa5e0e8e9e6f..1c5f502eae3f 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll @@ -82,14 +82,14 @@ newtype TDataFlowNode = performsVariableAccess(repr, var, kind, _) } or TCallableNode(DataFlowCallable callable) or - TReceiverParameterNode(DataFlowCallable callable) or - TReceiverArgumentNode(DataFlowCall call, Boolean isPost) or + TImplicitParameterNode(DataFlowCallable callable, ImplicitParameterPosition pos) or + TImplicitArgumentNode(DataFlowCall call, ImplicitArgumentPosition pos, Boolean isPost) or TLocalSsaNode(LocalSsaDataFlowOutput::SsaNode node) or TCaptureSsaNode(CaptureSsaOutput::SynthesizedCaptureNode node) class TDataFlowNodeStage1 = TValueNode or TStrictlyIncomingValue or TExprPostUpdateNode or TLocalVariableRefNode or - TCallableNode or TReceiverParameterNode or TReceiverArgumentNode; + TCallableNode or TImplicitParameterNode or TImplicitArgumentNode; class TDataFlowNodeStage2 = TDataFlowNodeStage1 or TLocalSsaNode; @@ -137,15 +137,14 @@ class BuilderNode extends TDataFlowNodeStage1 { /** Holds if this represents the updated state of the value returned by `expr` after it has been mutated by the surrounding assignment or call. */ predicate isPostUpdate(Expr expr) { this = TExprPostUpdateNode(expr) } - /** - * Holds if this represents the receiver passed to the given callable. - * - * Note that for non-methods and closures that capture the receiver from the enclosing method, - * this node still exists but will typically not flow anywhere. - */ - predicate isReceiverParameter(Callable callable) { - this.(BuilderNode) - .isReceiverParameterEx(any(DataFlowCallable c | c.asSourceCallable() = callable)) + /** Holds if this node represents an implicit parameter of `callable`. */ + predicate isImplicitParameter(DataFlowCallable callable, ImplicitParameterPosition pos) { + this = TImplicitParameterNode(callable, pos) + } + + /** Holds if this node represents an implicit argument to `call` (or its post-update). */ + predicate isImplicitArgument(DataFlowCall call, ImplicitArgumentPosition pos, boolean isPost) { + this = TImplicitArgumentNode(call, pos, isPost) } /** @@ -154,29 +153,21 @@ class BuilderNode extends TDataFlowNodeStage1 { * Note that for non-methods and closures that capture the receiver from the enclosing method, * this node still exists but will typically not flow anywhere. */ - predicate isReceiverParameterEx(DataFlowCallable callable) { - this = TReceiverParameterNode(callable) + predicate isReceiverParameter(Callable callable) { + this.isImplicitParameter(any(DataFlowCallable c | c.asSourceCallable() = callable), + any(ParameterPosition p | p.isReceiver())) } /** Holds if this node represents the receiver argument passed to `call`. */ predicate isReceiverArgument(CallExpr call) { - this.isReceiverArgumentEx(any(DataFlowCall c | c.asExplicitCall() = call)) + this.isImplicitArgument(any(DataFlowCall c | c.asExplicitCall() = call), + any(ArgumentPosition p | p.isReceiver()), false) } /** Holds if this node represents the updated state of the receiver of `call` after the call returns. */ predicate isReceiverPostUpdate(CallExpr call) { - this.isReceiverPostUpdateEx(any(DataFlowCall c | c.asExplicitCall() = call)) - } - - /** Holds if this node represents the receiver argument passed to `call`. */ - predicate isReceiverArgumentEx(DataFlowCall call) { this.isReceiverArgumentEx(call, false) } - - /** Holds if this node represents the updated state of the receiver of `call` after the call returns. */ - predicate isReceiverPostUpdateEx(DataFlowCall call) { this.isReceiverArgumentEx(call, true) } - - /** Holds if this node represents the receiver argument passed to `call`. */ - predicate isReceiverArgumentEx(DataFlowCall call, boolean isPost) { - this = TReceiverArgumentNode(call, isPost) + this.isImplicitArgument(any(DataFlowCall c | c.asExplicitCall() = call), + any(ArgumentPosition p | p.isReceiver()), true) } /** Holds if this is the canonical representative for the given `callable`. */ @@ -187,6 +178,16 @@ class BuilderNode extends TDataFlowNodeStage1 { this = TCallableNode(any(DataFlowCallable c | c.asSourceCallable() = callable)) } + /** Holds if this node represents the function being invoked at `call`. */ + predicate isCalleeArgument(CallExpr call) { + this.isImplicitArgument(getDataFlowCall(call), any(ArgumentPosition p | p.isCallee()), false) + } + + /** Holds if this node represents the updated state of the function being invoked at `call`, after the call returns. */ + predicate isCalleePostUpdate(CallExpr call) { + this.isImplicitArgument(getDataFlowCall(call), any(ArgumentPosition p | p.isCallee()), true) + } + /** * Gets the post-update node for this node, if any. * @@ -204,9 +205,9 @@ class BuilderNode extends TDataFlowNodeStage1 { result.isLocalVariablePostUpdate(expr, var) ) or - exists(DataFlowCall call | - this.isReceiverArgumentEx(call) and - result.isReceiverPostUpdateEx(call) + exists(DataFlowCall call, ArgumentPosition pos | + this.isImplicitArgument(call, pos, false) and + result.isImplicitArgument(call, pos, true) ) } @@ -237,20 +238,20 @@ class BuilderNode extends TDataFlowNodeStage1 { result = "[variable " + kind + "] " + v.toString() ) or - exists(DataFlowCallable callable | - this.isReceiverParameterEx(callable) and - result = "[receiver] " + callable.toString() + exists(DataFlowCallable callable, ParameterPosition pos | + this.isImplicitParameter(callable, pos) and + result = "[" + pos + " param] " + callable.toString() or this.isCallableEx(callable) and result = "[callable] " + callable.toString() ) or - exists(DataFlowCall call | - this.isReceiverArgumentEx(call) and - result = "[receiver arg] " + call.toString() + exists(DataFlowCall call, ArgumentPosition pos | + this.isImplicitArgument(call, pos, false) and + result = "[" + pos + " arg] " + call.toString() or - this.isReceiverPostUpdateEx(call) and - result = "[receiver post] " + call.toString() + this.isImplicitArgument(call, pos, true) and + result = "[" + pos + " post] " + call.toString() ) } @@ -264,7 +265,7 @@ class BuilderNode extends TDataFlowNodeStage1 { ) or exists(DataFlowCallable callable | - this.isReceiverParameterEx(callable) + this.isImplicitParameter(callable, _) or this.isCallableEx(callable) | @@ -272,7 +273,7 @@ class BuilderNode extends TDataFlowNodeStage1 { ) or exists(DataFlowCall call | - this.isReceiverArgumentEx(call, _) and + this.isImplicitArgument(call, _, _) and result = call.getLocation() ) } @@ -398,7 +399,7 @@ class Node extends TDataFlowNode { result.asSourceCallable() = node.getSourceVariable().getDeclaringCallable() ) or - this.(BuilderNode).isReceiverParameterEx(result) + this.(BuilderNode).isImplicitParameter(result, _) or exists(CaptureSsaOutput::SynthesizedCaptureNode node | this = TCaptureSsaNode(node) and @@ -408,7 +409,7 @@ class Node extends TDataFlowNode { this.(BuilderNode).isImplicitParameter(result, _) or exists(DataFlowCall call | - this.(BuilderNode).isReceiverArgumentEx(call, _) and + this.(BuilderNode).isImplicitArgument(call, _, _) and result = call.getEnclosingCallable() ) or @@ -446,19 +447,20 @@ class Node extends TDataFlowNode { ) or exists(DataFlowCallable callable | - this.(BuilderNode).isReceiverParameterEx(callable) and + this.(BuilderNode).isImplicitParameter(callable, _) and cfgNode.(ControlFlow::EntryNode).getEnclosingCallable() = callable.asSourceCallable() or this.isCallableEx(callable) and cfgNode.injects(callable.asSourceCallable()) ) or - exists(DataFlowCall call, CallExpr sourceCall | + exists(DataFlowCall call, CallExpr sourceCall, boolean isPost | call.asExplicitCall() = sourceCall and + this.(BuilderNode).isImplicitArgument(call, _, isPost) and ( - this.(BuilderNode).isReceiverArgumentEx(call) and cfgNode.injects(sourceCall) + isPost = false and cfgNode.injects(sourceCall) or - this.(BuilderNode).isReceiverPostUpdateEx(call) and cfgNode.isAfter(sourceCall) + isPost = true and cfgNode.isAfter(sourceCall) ) ) ) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll b/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll index e44d86484c2a..433123353e08 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/ParameterPositions.qll @@ -35,4 +35,12 @@ class ParameterPosition extends TParameterPosition { class ArgumentPosition = ParameterPosition; +/** A parameter position that is either `receiver` or `callee`. */ +class ImplicitParameterPosition extends ParameterPosition { + ImplicitParameterPosition() { this.isReceiver() or this.isCallee() } +} + +/** An argument position that is either `receiver` or `callee`. */ +class ImplicitArgumentPosition = ImplicitParameterPosition; + predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { apos = ppos } From ee7a50f5b1ef548c86951a07bdccc97e467ac4fd Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 10:29:17 +0200 Subject: [PATCH 26/40] unified: Add convenience getters --- .../unified/internal/dataflow/DataFlowCall.qll | 2 ++ .../unified/internal/dataflow/DataFlowCallable.qll | 2 ++ .../unified/internal/dataflow/DataFlowNode.qll | 12 ++++-------- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCall.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCall.qll index c316f91ba520..6e4e67d1e02c 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCall.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCall.qll @@ -28,3 +28,5 @@ class DataFlowCall extends TDataFlowCall { result.asSourceCallable() = this.asExplicitCall().getEnclosingCallable() } } + +DataFlowCall getDataFlowCall(CallExpr call) { result.asExplicitCall() = call } diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll index 8b67a7206ef5..d428239dcaf9 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowCallable.qll @@ -21,3 +21,5 @@ class DataFlowCallable extends TDataFlowCallable { /** Gets the location of this call, if any. */ Location getLocation() { result = this.asSourceCallable().getLocation() } } + +DataFlowCallable getDataFlowCallable(Callable callable) { result.asSourceCallable() = callable } diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll index 1c5f502eae3f..b57266e10af1 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll @@ -154,29 +154,25 @@ class BuilderNode extends TDataFlowNodeStage1 { * this node still exists but will typically not flow anywhere. */ predicate isReceiverParameter(Callable callable) { - this.isImplicitParameter(any(DataFlowCallable c | c.asSourceCallable() = callable), + this.isImplicitParameter(getDataFlowCallable(callable), any(ParameterPosition p | p.isReceiver())) } /** Holds if this node represents the receiver argument passed to `call`. */ predicate isReceiverArgument(CallExpr call) { - this.isImplicitArgument(any(DataFlowCall c | c.asExplicitCall() = call), - any(ArgumentPosition p | p.isReceiver()), false) + this.isImplicitArgument(getDataFlowCall(call), any(ArgumentPosition p | p.isReceiver()), false) } /** Holds if this node represents the updated state of the receiver of `call` after the call returns. */ predicate isReceiverPostUpdate(CallExpr call) { - this.isImplicitArgument(any(DataFlowCall c | c.asExplicitCall() = call), - any(ArgumentPosition p | p.isReceiver()), true) + this.isImplicitArgument(getDataFlowCall(call), any(ArgumentPosition p | p.isReceiver()), true) } /** Holds if this is the canonical representative for the given `callable`. */ predicate isCallableEx(DataFlowCallable callable) { this = TCallableNode(callable) } /** Holds if this is the canonical representative for the given `callable`. */ - predicate isCallable(Callable callable) { - this = TCallableNode(any(DataFlowCallable c | c.asSourceCallable() = callable)) - } + predicate isCallable(Callable callable) { this = TCallableNode(getDataFlowCallable(callable)) } /** Holds if this node represents the function being invoked at `call`. */ predicate isCalleeArgument(CallExpr call) { From 4cb2415fa696b2deaaaab43bfdac0e20337f125a Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 09:21:46 +0200 Subject: [PATCH 27/40] unified: Mapping capture nodes to data flow nodes --- .../unified/internal/dataflow/CaptureSsa.qll | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll b/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll index 555d814277a0..996596c299bb 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll @@ -111,3 +111,24 @@ module CaptureSsaInput implements InputSig { } module CaptureSsaOutput = Flow; + +Node getNodeFromCaptureSsaNode(CaptureSsaOutput::ClosureNode n) { + result = TCaptureSsaNode(n) + or + result = n.(CaptureSsaOutput::ExprNode).getExpr() + or + result = n.(CaptureSsaOutput::ExprPostUpdateNode).getExpr().(BuilderNode).getPostUpdateNode() + or + result = n.(CaptureSsaOutput::VariableWriteSourceNode).getVariableWrite() + or + // NOTE: This only supports lambdas at the moment. Local classes in Swift cannot capture variables. + result = n.(CaptureSsaOutput::MallocNode).getClosureExpr() + or + exists(CaptureSsaOutput::ThisParameterNode thisParam, Callable callable | + n = thisParam and + callable = thisParam.getCallable() and + result + .(BuilderNode) + .isImplicitParameter(getDataFlowCallable(callable), any(ParameterPosition p | p.isCallee())) + ) +} From 976c100c9d692415c781d2fa0402b1118867d916 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 13:54:10 +0200 Subject: [PATCH 28/40] unified: Add CapturedVariable content --- .../codeql/unified/internal/dataflow/Content.qll | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/Content.qll b/unified/ql/lib/codeql/unified/internal/dataflow/Content.qll index 73a3d7da2c9d..e2d16310526e 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/Content.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/Content.qll @@ -8,14 +8,19 @@ private newtype TContent = // Tuple elements can be accessed as named members, e.g. `tuple.0`, `tuple.1`, etc, // so just model their elements as named members. name = [0 .. 20].toString() - } + } or + TCapturedVariable(CaptureSsaInput::CapturedVariable v) class Content extends TContent { string asNamedMember() { this = TNamedMember(result) } - string toString() { result = this.asNamedMember() } + string toString() { + result = this.asNamedMember() or result = this.asCapturedVariable().toString() + } + + LocalVariable asCapturedVariable() { this = TCapturedVariable(result) } - Location getLocation() { none() } + Location getLocation() { result = this.asCapturedVariable().getLocation() } } private newtype TContentSet = TSingleton(Content content) @@ -34,4 +39,6 @@ class ContentSet extends TContentSet { module ContentSet { ContentSet namedMember(string name) { result.asSingleton().asNamedMember() = name } + + ContentSet capturedVariable(LocalVariable v) { result.asSingleton().asCapturedVariable() = v } } From 917f07f6d82d19316c31a85d1a21acad77ebefb9 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 13:58:43 +0200 Subject: [PATCH 29/40] unified: Add CaptureSsa steps and post-updates --- .../unified/internal/dataflow/CaptureSsa.qll | 42 ++++++++++++++++++- .../dataflow/DataFlowInstantiation.qll | 10 ++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll b/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll index 996596c299bb..de94f39a77fb 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll @@ -106,7 +106,9 @@ module CaptureSsaInput implements InputSig { predicate hasBody(Callable body) { callable = body } - predicate hasAliasedAccess(Expr f) { callableHasLocalAlias(callable, f) } + predicate hasAliasedAccess(Expr f) { + callableHasLocalAlias(callable, f) and not f.(LocalVariableRefNode).getRefKind().isWrite() + } } } @@ -132,3 +134,41 @@ Node getNodeFromCaptureSsaNode(CaptureSsaOutput::ClosureNode n) { .isImplicitParameter(getDataFlowCallable(callable), any(ParameterPosition p | p.isCallee())) ) } + +CaptureSsaOutput::ClosureNode getCaptureSsaNodeFromNode(Node n) { + n = getNodeFromCaptureSsaNode(result) +} + +predicate captureSsaLocalFlowStep(Node node1, Node node2) { + CaptureSsaOutput::localFlowStep(getCaptureSsaNodeFromNode(node1), getCaptureSsaNodeFromNode(node2)) +} + +predicate captureSsaStoreStep(Node node1, ContentSet contents, Node node2) { + CaptureSsaOutput::storeStep(getCaptureSsaNodeFromNode(node1), + contents.asSingleton().asCapturedVariable(), getCaptureSsaNodeFromNode(node2)) +} + +predicate captureSsaReadStep(Node node1, ContentSet contents, Node node2) { + CaptureSsaOutput::readStep(getCaptureSsaNodeFromNode(node1), + contents.asSingleton().asCapturedVariable(), getCaptureSsaNodeFromNode(node2)) +} + +predicate captureSsaClearsContent(Node node, ContentSet contents) { + CaptureSsaOutput::clearsContent(getCaptureSsaNodeFromNode(node), + contents.asSingleton().asCapturedVariable()) +} + +Node getCaptureSsaPostUpdate(Node pre) { + CaptureSsaOutput::capturePostUpdateNode(getCaptureSsaNodeFromNode(result), + getCaptureSsaNodeFromNode(pre)) +} + +predicate captureSsaAllowParameterReturnInSelf(Node param) { + exists(Callable callable | + CaptureSsaOutput::heuristicAllowInstanceParameterReturnInSelf(callable) and + param = + getNodeFromCaptureSsaNode(any(CaptureSsaOutput::ThisParameterNode n | + n.getCallable() = callable + )) + ) +} diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll index a7c85c39a0f6..e0b336577460 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll @@ -129,19 +129,25 @@ module DataFlowInput implements InputSig { step(node1, any(Step s | s.value()), node2) and model = "" or localSsaStep(node1, node2, _) and model = "" + or + captureSsaLocalFlowStep(node1, node2) and model = "" } predicate jumpStep(Node node1, Node node2) { step(node1, any(Step s | s.jump()), node2) } predicate readStep(Node node1, ContentSet c, Node node2) { step(node1, any(Step s | s.read(c)), node2) + or + captureSsaReadStep(node1, c, node2) } predicate storeStep(Node node1, ContentSet c, Node node2) { step(node1, any(Step s | s.store(c)), node2) + or + captureSsaStoreStep(node1, c, node2) } - predicate clearsContent(Node n, ContentSet c) { none() } // TODO + predicate clearsContent(Node n, ContentSet c) { captureSsaClearsContent(n, c) } predicate expectsContent(Node n, ContentSet c) { none() } // TODO @@ -181,7 +187,7 @@ module DataFlowInput implements InputSig { predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() } // TODO - predicate allowParameterReturnInSelf(ParameterNode p) { none() } // TODO + predicate allowParameterReturnInSelf(ParameterNode p) { captureSsaAllowParameterReturnInSelf(p) } class LambdaCallKind extends Void { LambdaCallKind() { none() } // TODO From 9a4672914c4dc78234e81d2d9c125cdd2ec6ffd0 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 13:58:53 +0200 Subject: [PATCH 30/40] unified: Update debug graph --- .../internal/dataflow/DataFlowGraph.qll | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll index 090b9f5f2902..5cfeed031bb6 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll @@ -132,14 +132,24 @@ predicate step(BuilderNode node1, Step step, BuilderNode node2) { private signature predicate relevantNodeSig(AstNode node); module DebugGraph { - private Node adjacent(Node n) { + private Node adjacent1(Node n) { step(n, _, result) or - step(result, _, n) - or localSsaStep(n, result, _) or - localSsaStep(result, n, _) + captureSsaLocalFlowStep(n, result) + or + captureSsaReadStep(n, _, result) + or + captureSsaStoreStep(n, _, result) + or + result = n.getPostUpdateNode() + } + + private Node adjacent(Node n) { + result = adjacent1(n) + or + n = adjacent1(result) } private predicate relevantDataFlowNode(Node node) { @@ -149,10 +159,16 @@ module DebugGraph { relevantDataFlowNode(adjacent(node)) } + private string getANodeAnnotation(Node n) { + result = + " [capture-clear: " + + strictconcat(ContentSet c | captureSsaClearsContent(n, c) | c.toString(), ",") + "]" + } + query predicate nodes(Node node, string key, string value) { relevantDataFlowNode(node) and key = "semmle.label" and - value = node.toString() + value = node.toString() + concat(getANodeAnnotation(node)) } query predicate edges(Node node1, Node node2, string key, string value) { @@ -172,6 +188,17 @@ module DebugGraph { or node2 = node1.getPostUpdateNode() and value = "post-update" + or + captureSsaLocalFlowStep(node1, node2) and + value = "value" + or + exists(ContentSet contents | + captureSsaReadStep(node1, contents, node2) and + value = "read[" + contents.toString() + "]" + or + captureSsaStoreStep(node1, contents, node2) and + value = "store[" + contents.toString() + "]" + ) ) } } From bf20e6b64fa3515d6862fe46bb69e1a5fa09284b Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 13:59:07 +0200 Subject: [PATCH 31/40] unified: Add lambda flow --- .../dataflow/DataFlowInstantiation.qll | 14 ++-- .../test/library-tests/dataflow/capture.swift | 14 ++-- .../test/library-tests/dataflow/test.expected | 77 +++++++++++++++++++ 3 files changed, 92 insertions(+), 13 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll index e0b336577460..e8bcf53e801f 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll @@ -189,15 +189,17 @@ module DataFlowInput implements InputSig { predicate allowParameterReturnInSelf(ParameterNode p) { captureSsaAllowParameterReturnInSelf(p) } - class LambdaCallKind extends Void { - LambdaCallKind() { none() } // TODO + class LambdaCallKind extends Unit { } - string toString() { none() } // TODO + predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { + creation.isCallableEx(c) and + exists(kind) } - predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { none() } // TODO - - predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { none() } // TODO + predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { + receiver.(BuilderNode).isImplicitArgument(call, any(ArgumentPosition p | p.isCallee()), false) and + exists(kind) + } predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() // TODO diff --git a/unified/ql/test/library-tests/dataflow/capture.swift b/unified/ql/test/library-tests/dataflow/capture.swift index 320a1b76472a..b4d4a2456b97 100644 --- a/unified/ql/test/library-tests/dataflow/capture.swift +++ b/unified/ql/test/library-tests/dataflow/capture.swift @@ -9,7 +9,7 @@ func sink(_ s: String) -> String { func t1() { let x = source("t1.1") let closure = { (_: Int) in - sink(x) // $ MISSING: hasValueFlow="t1.1" + sink(x) // $ hasValueFlow=t1.1 } closure(123) } @@ -21,7 +21,7 @@ func t2() { } sink(x) // no flow closure(123) - sink(x) // $ MISSING: hasValueFlow="t2.1" + sink(x) // $ hasValueFlow=t2.1 } func t3() { @@ -35,8 +35,8 @@ func t3() { sink(y1) // no flow sink(y2) // no flow closure(123) - sink(y1) // $ MISSING: hasValueFlow="t3.1" - sink(y2) // $ MISSING: hasTaintFlow="t3.1" + sink(y1) // $ hasValueFlow=t3.1 + sink(y2) // $ hasTaintFlow=t3.1 } func t4() { @@ -47,7 +47,7 @@ func t4() { } sink(y) // no flow closure(x) - sink(y) // $ MISSING: hasValueFlow="t4.1" + sink(y) // $ hasValueFlow=t4.1 } func t5() { @@ -58,13 +58,13 @@ func t5() { } sink(y.0) // no flow closure(x) - sink(y.0) // $ MISSING: hasValueFlow="t5.1" + sink(y.0) // $ hasValueFlow=t5.1 } func t6() { var x = "safe" let closure = { (_: Int) in - sink(x) // $ MISSING: hasValueFlow="t6.1" + sink(x) // $ hasValueFlow=t6.1 } x = source("t6.1") closure(123) diff --git a/unified/ql/test/library-tests/dataflow/test.expected b/unified/ql/test/library-tests/dataflow/test.expected index 478e0e3edfa3..3baba3ed9e32 100644 --- a/unified/ql/test/library-tests/dataflow/test.expected +++ b/unified/ql/test/library-tests/dataflow/test.expected @@ -38,6 +38,36 @@ edges | calls.swift:99:18:99:21 | self [field] | calls.swift:99:18:99:27 | ... .field | provenance | | | calls.swift:111:18:111:21 | self [field] | calls.swift:111:18:111:27 | ... .field | provenance | | | calls.swift:123:18:123:21 | self [field] | calls.swift:123:18:123:27 | ... .field | provenance | | +| capture.swift:10:9:10:9 | x | capture.swift:14:5:14:11 | closure [x] | provenance | | +| capture.swift:10:13:10:26 | source(...) | capture.swift:10:9:10:9 | x | provenance | | +| capture.swift:14:5:14:11 | closure [x] | capture.swift:12:14:12:14 | x | provenance | | +| capture.swift:20:9:20:9 | x | capture.swift:24:10:24:10 | x | provenance | | +| capture.swift:20:13:20:26 | source(...) | capture.swift:20:9:20:9 | x | provenance | | +| capture.swift:28:9:28:9 | x | capture.swift:37:5:37:11 | closure [x] | provenance | | +| capture.swift:28:13:28:26 | source(...) | capture.swift:28:9:28:9 | x | provenance | | +| capture.swift:32:14:32:14 | x | capture.swift:32:9:32:10 | y1 | provenance | | +| capture.swift:33:14:33:14 | x | capture.swift:33:9:33:10 | y2 | provenance | | +| capture.swift:37:5:37:11 | closure [x] | capture.swift:32:14:32:14 | x | provenance | | +| capture.swift:37:5:37:11 | closure [x] | capture.swift:33:14:33:14 | x | provenance | | +| capture.swift:37:5:37:11 | closure [x] | capture.swift:38:10:38:11 | y1 | provenance | | +| capture.swift:37:5:37:11 | closure [x] | capture.swift:39:10:39:11 | y2 | provenance | | +| capture.swift:43:9:43:9 | x | capture.swift:49:13:49:13 | x | provenance | | +| capture.swift:43:13:43:26 | source(...) | capture.swift:43:9:43:9 | x | provenance | | +| capture.swift:45:22:45:24 | arg | capture.swift:46:13:46:15 | arg | provenance | | +| capture.swift:46:13:46:15 | arg | capture.swift:46:9:46:9 | y | provenance | | +| capture.swift:49:13:49:13 | x | capture.swift:45:22:45:24 | arg | provenance | | +| capture.swift:49:13:49:13 | x | capture.swift:50:10:50:10 | y | provenance | | +| capture.swift:54:9:54:9 | x | capture.swift:60:13:60:13 | x | provenance | | +| capture.swift:54:13:54:26 | source(...) | capture.swift:54:9:54:9 | x | provenance | | +| capture.swift:56:22:56:24 | arg | capture.swift:57:15:57:17 | arg | provenance | | +| capture.swift:57:9:57:11 | ... .0 | capture.swift:57:9:57:9 | [post] y [0] | provenance | | +| capture.swift:57:15:57:17 | arg | capture.swift:57:9:57:11 | ... .0 | provenance | | +| capture.swift:60:13:60:13 | x | capture.swift:56:22:56:24 | arg | provenance | | +| capture.swift:60:13:60:13 | x | capture.swift:61:10:61:10 | y [0] | provenance | | +| capture.swift:61:10:61:10 | y [0] | capture.swift:61:10:61:12 | ... .0 | provenance | | +| capture.swift:69:5:69:5 | x | capture.swift:70:5:70:11 | closure [x] | provenance | | +| capture.swift:69:9:69:22 | source(...) | capture.swift:69:5:69:5 | x | provenance | | +| capture.swift:70:5:70:11 | closure [x] | capture.swift:67:14:67:14 | x | provenance | | | implicit-self.swift:16:9:16:12 | [post] self [x] | implicit-self.swift:17:14:17:17 | self [x] | provenance | | | implicit-self.swift:16:9:16:14 | ... .x | implicit-self.swift:16:9:16:12 | [post] self [x] | provenance | | | implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:16:9:16:14 | ... .x | provenance | | @@ -231,6 +261,42 @@ nodes | calls.swift:117:18:117:22 | field | semmle.label | field | | calls.swift:123:18:123:21 | self [field] | semmle.label | self [field] | | calls.swift:123:18:123:27 | ... .field | semmle.label | ... .field | +| capture.swift:10:9:10:9 | x | semmle.label | x | +| capture.swift:10:13:10:26 | source(...) | semmle.label | source(...) | +| capture.swift:12:14:12:14 | x | semmle.label | x | +| capture.swift:14:5:14:11 | closure [x] | semmle.label | closure [x] | +| capture.swift:20:9:20:9 | x | semmle.label | x | +| capture.swift:20:13:20:26 | source(...) | semmle.label | source(...) | +| capture.swift:24:10:24:10 | x | semmle.label | x | +| capture.swift:28:9:28:9 | x | semmle.label | x | +| capture.swift:28:13:28:26 | source(...) | semmle.label | source(...) | +| capture.swift:32:9:32:10 | y1 | semmle.label | y1 | +| capture.swift:32:14:32:14 | x | semmle.label | x | +| capture.swift:33:9:33:10 | y2 | semmle.label | y2 | +| capture.swift:33:14:33:14 | x | semmle.label | x | +| capture.swift:37:5:37:11 | closure [x] | semmle.label | closure [x] | +| capture.swift:38:10:38:11 | y1 | semmle.label | y1 | +| capture.swift:39:10:39:11 | y2 | semmle.label | y2 | +| capture.swift:43:9:43:9 | x | semmle.label | x | +| capture.swift:43:13:43:26 | source(...) | semmle.label | source(...) | +| capture.swift:45:22:45:24 | arg | semmle.label | arg | +| capture.swift:46:9:46:9 | y | semmle.label | y | +| capture.swift:46:13:46:15 | arg | semmle.label | arg | +| capture.swift:49:13:49:13 | x | semmle.label | x | +| capture.swift:50:10:50:10 | y | semmle.label | y | +| capture.swift:54:9:54:9 | x | semmle.label | x | +| capture.swift:54:13:54:26 | source(...) | semmle.label | source(...) | +| capture.swift:56:22:56:24 | arg | semmle.label | arg | +| capture.swift:57:9:57:9 | [post] y [0] | semmle.label | [post] y [0] | +| capture.swift:57:9:57:11 | ... .0 | semmle.label | ... .0 | +| capture.swift:57:15:57:17 | arg | semmle.label | arg | +| capture.swift:60:13:60:13 | x | semmle.label | x | +| capture.swift:61:10:61:10 | y [0] | semmle.label | y [0] | +| capture.swift:61:10:61:12 | ... .0 | semmle.label | ... .0 | +| capture.swift:67:14:67:14 | x | semmle.label | x | +| capture.swift:69:5:69:5 | x | semmle.label | x | +| capture.swift:69:9:69:22 | source(...) | semmle.label | source(...) | +| capture.swift:70:5:70:11 | closure [x] | semmle.label | closure [x] | | implicit-self.swift:16:9:16:12 | [post] self [x] | semmle.label | [post] self [x] | | implicit-self.swift:16:9:16:14 | ... .x | semmle.label | ... .x | | implicit-self.swift:16:18:16:31 | source(...) | semmle.label | source(...) | @@ -420,6 +486,10 @@ nodes subpaths | calls.swift:31:17:31:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:31:10:31:31 | target(...) | | calls.swift:32:17:32:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:32:10:32:31 | target(...) | +| capture.swift:37:5:37:11 | closure [x] | capture.swift:32:14:32:14 | x | capture.swift:32:9:32:10 | y1 | capture.swift:38:10:38:11 | y1 | +| capture.swift:37:5:37:11 | closure [x] | capture.swift:33:14:33:14 | x | capture.swift:33:9:33:10 | y2 | capture.swift:39:10:39:11 | y2 | +| capture.swift:49:13:49:13 | x | capture.swift:45:22:45:24 | arg | capture.swift:46:9:46:9 | y | capture.swift:50:10:50:10 | y | +| capture.swift:60:13:60:13 | x | capture.swift:56:22:56:24 | arg | capture.swift:57:9:57:9 | [post] y [0] | capture.swift:61:10:61:10 | y [0] | testFailures #select | calls.swift:8:14:8:14 | x | calls.swift:10:12:10:25 | source(...) | calls.swift:8:14:8:14 | x | $@ | calls.swift:10:12:10:25 | source(...) | source(...) | @@ -440,6 +510,13 @@ testFailures | calls.swift:111:18:111:27 | ... .field | calls.swift:75:21:75:34 | source(...) | calls.swift:111:18:111:27 | ... .field | $@ | calls.swift:75:21:75:34 | source(...) | source(...) | | calls.swift:117:18:117:22 | field | calls.swift:75:21:75:34 | source(...) | calls.swift:117:18:117:22 | field | $@ | calls.swift:75:21:75:34 | source(...) | source(...) | | calls.swift:123:18:123:27 | ... .field | calls.swift:75:21:75:34 | source(...) | calls.swift:123:18:123:27 | ... .field | $@ | calls.swift:75:21:75:34 | source(...) | source(...) | +| capture.swift:12:14:12:14 | x | capture.swift:10:13:10:26 | source(...) | capture.swift:12:14:12:14 | x | $@ | capture.swift:10:13:10:26 | source(...) | source(...) | +| capture.swift:24:10:24:10 | x | capture.swift:20:13:20:26 | source(...) | capture.swift:24:10:24:10 | x | $@ | capture.swift:20:13:20:26 | source(...) | source(...) | +| capture.swift:38:10:38:11 | y1 | capture.swift:28:13:28:26 | source(...) | capture.swift:38:10:38:11 | y1 | $@ | capture.swift:28:13:28:26 | source(...) | source(...) | +| capture.swift:39:10:39:11 | y2 | capture.swift:28:13:28:26 | source(...) | capture.swift:39:10:39:11 | y2 | $@ | capture.swift:28:13:28:26 | source(...) | source(...) | +| capture.swift:50:10:50:10 | y | capture.swift:43:13:43:26 | source(...) | capture.swift:50:10:50:10 | y | $@ | capture.swift:43:13:43:26 | source(...) | source(...) | +| capture.swift:61:10:61:12 | ... .0 | capture.swift:54:13:54:26 | source(...) | capture.swift:61:10:61:12 | ... .0 | $@ | capture.swift:54:13:54:26 | source(...) | source(...) | +| capture.swift:67:14:67:14 | x | capture.swift:69:9:69:22 | source(...) | capture.swift:67:14:67:14 | x | $@ | capture.swift:69:9:69:22 | source(...) | source(...) | | implicit-self.swift:17:14:17:19 | ... .x | implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:17:14:17:19 | ... .x | $@ | implicit-self.swift:16:18:16:31 | source(...) | source(...) | | implicit-self.swift:23:14:23:14 | x | implicit-self.swift:22:13:22:26 | source(...) | implicit-self.swift:23:14:23:14 | x | $@ | implicit-self.swift:22:13:22:26 | source(...) | source(...) | | implicit-self.swift:29:14:29:19 | ... .x | implicit-self.swift:28:13:28:26 | source(...) | implicit-self.swift:29:14:29:19 | ... .x | $@ | implicit-self.swift:28:13:28:26 | source(...) | source(...) | From 487d1657621c7a67fe75cb730a80aef21efef3fa Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 14:49:18 +0200 Subject: [PATCH 32/40] unified: Add some tests with local function declarations --- .../test/library-tests/dataflow/capture.swift | 18 ++++++++++++++++++ .../test/library-tests/dataflow/test.expected | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/unified/ql/test/library-tests/dataflow/capture.swift b/unified/ql/test/library-tests/dataflow/capture.swift index b4d4a2456b97..4e0bebe609fd 100644 --- a/unified/ql/test/library-tests/dataflow/capture.swift +++ b/unified/ql/test/library-tests/dataflow/capture.swift @@ -69,3 +69,21 @@ func t6() { x = source("t6.1") closure(123) } + +func t7() { + let x = source("t7.1") + func local(_: Int) { + sink(x) // $ hasValueFlow=t7.1 + } + local(123) +} + +func t8() { + var x = "safe" + func local(arg: Int) { + x = source("t8.1") + } + sink(x) // no flow + local(arg: 123) + sink(x) // $ hasValueFlow=t8.1 +} diff --git a/unified/ql/test/library-tests/dataflow/test.expected b/unified/ql/test/library-tests/dataflow/test.expected index 3baba3ed9e32..520978666611 100644 --- a/unified/ql/test/library-tests/dataflow/test.expected +++ b/unified/ql/test/library-tests/dataflow/test.expected @@ -68,6 +68,11 @@ edges | capture.swift:69:5:69:5 | x | capture.swift:70:5:70:11 | closure [x] | provenance | | | capture.swift:69:9:69:22 | source(...) | capture.swift:69:5:69:5 | x | provenance | | | capture.swift:70:5:70:11 | closure [x] | capture.swift:67:14:67:14 | x | provenance | | +| capture.swift:74:9:74:9 | x | capture.swift:78:5:78:9 | local [x] | provenance | | +| capture.swift:74:13:74:26 | source(...) | capture.swift:74:9:74:9 | x | provenance | | +| capture.swift:78:5:78:9 | local [x] | capture.swift:76:14:76:14 | x | provenance | | +| capture.swift:84:9:84:9 | x | capture.swift:88:10:88:10 | x | provenance | | +| capture.swift:84:13:84:26 | source(...) | capture.swift:84:9:84:9 | x | provenance | | | implicit-self.swift:16:9:16:12 | [post] self [x] | implicit-self.swift:17:14:17:17 | self [x] | provenance | | | implicit-self.swift:16:9:16:14 | ... .x | implicit-self.swift:16:9:16:12 | [post] self [x] | provenance | | | implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:16:9:16:14 | ... .x | provenance | | @@ -297,6 +302,13 @@ nodes | capture.swift:69:5:69:5 | x | semmle.label | x | | capture.swift:69:9:69:22 | source(...) | semmle.label | source(...) | | capture.swift:70:5:70:11 | closure [x] | semmle.label | closure [x] | +| capture.swift:74:9:74:9 | x | semmle.label | x | +| capture.swift:74:13:74:26 | source(...) | semmle.label | source(...) | +| capture.swift:76:14:76:14 | x | semmle.label | x | +| capture.swift:78:5:78:9 | local [x] | semmle.label | local [x] | +| capture.swift:84:9:84:9 | x | semmle.label | x | +| capture.swift:84:13:84:26 | source(...) | semmle.label | source(...) | +| capture.swift:88:10:88:10 | x | semmle.label | x | | implicit-self.swift:16:9:16:12 | [post] self [x] | semmle.label | [post] self [x] | | implicit-self.swift:16:9:16:14 | ... .x | semmle.label | ... .x | | implicit-self.swift:16:18:16:31 | source(...) | semmle.label | source(...) | @@ -517,6 +529,8 @@ testFailures | capture.swift:50:10:50:10 | y | capture.swift:43:13:43:26 | source(...) | capture.swift:50:10:50:10 | y | $@ | capture.swift:43:13:43:26 | source(...) | source(...) | | capture.swift:61:10:61:12 | ... .0 | capture.swift:54:13:54:26 | source(...) | capture.swift:61:10:61:12 | ... .0 | $@ | capture.swift:54:13:54:26 | source(...) | source(...) | | capture.swift:67:14:67:14 | x | capture.swift:69:9:69:22 | source(...) | capture.swift:67:14:67:14 | x | $@ | capture.swift:69:9:69:22 | source(...) | source(...) | +| capture.swift:76:14:76:14 | x | capture.swift:74:13:74:26 | source(...) | capture.swift:76:14:76:14 | x | $@ | capture.swift:74:13:74:26 | source(...) | source(...) | +| capture.swift:88:10:88:10 | x | capture.swift:84:13:84:26 | source(...) | capture.swift:88:10:88:10 | x | $@ | capture.swift:84:13:84:26 | source(...) | source(...) | | implicit-self.swift:17:14:17:19 | ... .x | implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:17:14:17:19 | ... .x | $@ | implicit-self.swift:16:18:16:31 | source(...) | source(...) | | implicit-self.swift:23:14:23:14 | x | implicit-self.swift:22:13:22:26 | source(...) | implicit-self.swift:23:14:23:14 | x | $@ | implicit-self.swift:22:13:22:26 | source(...) | source(...) | | implicit-self.swift:29:14:29:19 | ... .x | implicit-self.swift:28:13:28:26 | source(...) | implicit-self.swift:29:14:29:19 | ... .x | $@ | implicit-self.swift:28:13:28:26 | source(...) | source(...) | From 479aa616ad567699b6984bcda46371f911f1422d Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 14:53:43 +0200 Subject: [PATCH 33/40] unified: Add test with local function used before its declaration --- unified/ql/test/library-tests/dataflow/capture.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/unified/ql/test/library-tests/dataflow/capture.swift b/unified/ql/test/library-tests/dataflow/capture.swift index 4e0bebe609fd..2031f2c4f107 100644 --- a/unified/ql/test/library-tests/dataflow/capture.swift +++ b/unified/ql/test/library-tests/dataflow/capture.swift @@ -87,3 +87,15 @@ func t8() { local(arg: 123) sink(x) // $ hasValueFlow=t8.1 } + +func t9() { + // Use of a local function before its declaration + let x = source("t9.1") + let y = local() + sink(y) // $ MISSING: hasValueFlow=t9.1 + + func local() -> String { + sink(x) // $ MISSING: hasValueFlow=t9.1 + return x + } +} From ba544c575711501ff93181a78c954f19e3ebc605 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 15:00:16 +0200 Subject: [PATCH 34/40] unified: Hoist local functions --- .../unified/internal/dataflow/DataFlowNode.qll | 5 +++++ .../test/library-tests/dataflow/capture.swift | 4 ++-- .../test/library-tests/dataflow/test.expected | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll index b57266e10af1..824cd2f43191 100644 --- a/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll +++ b/unified/ql/lib/codeql/unified/internal/dataflow/DataFlowNode.qll @@ -14,10 +14,15 @@ private predicate hasIncomingValueAtCfgNode(Expr expr, ControlFlowNode cfgNode) // Use the after node. cfgNode.isAfter(declOrAssignment.(VariableDeclaration)) or + // Hoist local functions to the top of their block + declOrAssignment instanceof LocalFunctionDeclaration and + cfgNode.isBefore(declOrAssignment.getParent()) + or // In other cases, it's a binding pattern whose CFG node can be used // as its assignment time not declOrAssignment instanceof Assignment and not declOrAssignment instanceof VariableDeclaration and + not declOrAssignment instanceof LocalFunctionDeclaration and cfgNode.injects(expr) ) } diff --git a/unified/ql/test/library-tests/dataflow/capture.swift b/unified/ql/test/library-tests/dataflow/capture.swift index 2031f2c4f107..d67d4d3ab9fc 100644 --- a/unified/ql/test/library-tests/dataflow/capture.swift +++ b/unified/ql/test/library-tests/dataflow/capture.swift @@ -92,10 +92,10 @@ func t9() { // Use of a local function before its declaration let x = source("t9.1") let y = local() - sink(y) // $ MISSING: hasValueFlow=t9.1 + sink(y) // $ hasValueFlow=t9.1 func local() -> String { - sink(x) // $ MISSING: hasValueFlow=t9.1 + sink(x) // $ hasValueFlow=t9.1 return x } } diff --git a/unified/ql/test/library-tests/dataflow/test.expected b/unified/ql/test/library-tests/dataflow/test.expected index 520978666611..b164e3a67b2e 100644 --- a/unified/ql/test/library-tests/dataflow/test.expected +++ b/unified/ql/test/library-tests/dataflow/test.expected @@ -73,6 +73,13 @@ edges | capture.swift:78:5:78:9 | local [x] | capture.swift:76:14:76:14 | x | provenance | | | capture.swift:84:9:84:9 | x | capture.swift:88:10:88:10 | x | provenance | | | capture.swift:84:13:84:26 | source(...) | capture.swift:84:9:84:9 | x | provenance | | +| capture.swift:93:9:93:9 | x | capture.swift:94:13:94:17 | local [x] | provenance | | +| capture.swift:93:13:93:26 | source(...) | capture.swift:93:9:93:9 | x | provenance | | +| capture.swift:94:9:94:9 | y | capture.swift:95:10:95:10 | y | provenance | | +| capture.swift:94:13:94:17 | local [x] | capture.swift:94:13:94:19 | local(...) | provenance | | +| capture.swift:94:13:94:17 | local [x] | capture.swift:98:14:98:14 | x | provenance | | +| capture.swift:94:13:94:17 | local [x] | capture.swift:99:16:99:16 | x | provenance | | +| capture.swift:94:13:94:19 | local(...) | capture.swift:94:9:94:9 | y | provenance | | | implicit-self.swift:16:9:16:12 | [post] self [x] | implicit-self.swift:17:14:17:17 | self [x] | provenance | | | implicit-self.swift:16:9:16:14 | ... .x | implicit-self.swift:16:9:16:12 | [post] self [x] | provenance | | | implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:16:9:16:14 | ... .x | provenance | | @@ -309,6 +316,14 @@ nodes | capture.swift:84:9:84:9 | x | semmle.label | x | | capture.swift:84:13:84:26 | source(...) | semmle.label | source(...) | | capture.swift:88:10:88:10 | x | semmle.label | x | +| capture.swift:93:9:93:9 | x | semmle.label | x | +| capture.swift:93:13:93:26 | source(...) | semmle.label | source(...) | +| capture.swift:94:9:94:9 | y | semmle.label | y | +| capture.swift:94:13:94:17 | local [x] | semmle.label | local [x] | +| capture.swift:94:13:94:19 | local(...) | semmle.label | local(...) | +| capture.swift:95:10:95:10 | y | semmle.label | y | +| capture.swift:98:14:98:14 | x | semmle.label | x | +| capture.swift:99:16:99:16 | x | semmle.label | x | | implicit-self.swift:16:9:16:12 | [post] self [x] | semmle.label | [post] self [x] | | implicit-self.swift:16:9:16:14 | ... .x | semmle.label | ... .x | | implicit-self.swift:16:18:16:31 | source(...) | semmle.label | source(...) | @@ -502,6 +517,7 @@ subpaths | capture.swift:37:5:37:11 | closure [x] | capture.swift:33:14:33:14 | x | capture.swift:33:9:33:10 | y2 | capture.swift:39:10:39:11 | y2 | | capture.swift:49:13:49:13 | x | capture.swift:45:22:45:24 | arg | capture.swift:46:9:46:9 | y | capture.swift:50:10:50:10 | y | | capture.swift:60:13:60:13 | x | capture.swift:56:22:56:24 | arg | capture.swift:57:9:57:9 | [post] y [0] | capture.swift:61:10:61:10 | y [0] | +| capture.swift:94:13:94:17 | local [x] | capture.swift:99:16:99:16 | x | capture.swift:99:16:99:16 | x | capture.swift:94:13:94:19 | local(...) | testFailures #select | calls.swift:8:14:8:14 | x | calls.swift:10:12:10:25 | source(...) | calls.swift:8:14:8:14 | x | $@ | calls.swift:10:12:10:25 | source(...) | source(...) | @@ -531,6 +547,8 @@ testFailures | capture.swift:67:14:67:14 | x | capture.swift:69:9:69:22 | source(...) | capture.swift:67:14:67:14 | x | $@ | capture.swift:69:9:69:22 | source(...) | source(...) | | capture.swift:76:14:76:14 | x | capture.swift:74:13:74:26 | source(...) | capture.swift:76:14:76:14 | x | $@ | capture.swift:74:13:74:26 | source(...) | source(...) | | capture.swift:88:10:88:10 | x | capture.swift:84:13:84:26 | source(...) | capture.swift:88:10:88:10 | x | $@ | capture.swift:84:13:84:26 | source(...) | source(...) | +| capture.swift:95:10:95:10 | y | capture.swift:93:13:93:26 | source(...) | capture.swift:95:10:95:10 | y | $@ | capture.swift:93:13:93:26 | source(...) | source(...) | +| capture.swift:98:14:98:14 | x | capture.swift:93:13:93:26 | source(...) | capture.swift:98:14:98:14 | x | $@ | capture.swift:93:13:93:26 | source(...) | source(...) | | implicit-self.swift:17:14:17:19 | ... .x | implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:17:14:17:19 | ... .x | $@ | implicit-self.swift:16:18:16:31 | source(...) | source(...) | | implicit-self.swift:23:14:23:14 | x | implicit-self.swift:22:13:22:26 | source(...) | implicit-self.swift:23:14:23:14 | x | $@ | implicit-self.swift:22:13:22:26 | source(...) | source(...) | | implicit-self.swift:29:14:29:19 | ... .x | implicit-self.swift:28:13:28:26 | source(...) | implicit-self.swift:29:14:29:19 | ... .x | $@ | implicit-self.swift:28:13:28:26 | source(...) | source(...) | From ea1c52e1392adc42e044cf8519ff1ed65e599604 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 15:38:30 +0200 Subject: [PATCH 35/40] unified: Add tests with capture declarations --- .../test/library-tests/dataflow/capture.swift | 80 +++++++++++++++++++ .../test/library-tests/dataflow/test.expected | 31 +++++++ 2 files changed, 111 insertions(+) diff --git a/unified/ql/test/library-tests/dataflow/capture.swift b/unified/ql/test/library-tests/dataflow/capture.swift index d67d4d3ab9fc..aabd9201e5da 100644 --- a/unified/ql/test/library-tests/dataflow/capture.swift +++ b/unified/ql/test/library-tests/dataflow/capture.swift @@ -99,3 +99,83 @@ func t9() { return x } } + +func t10() { + let x = source("t10.1") + let closure1 = { [x1 = x] in + sink(x1) // $ MISSING: hasValueFlow=t10.1 + } + let closure2 = { [x] in + sink(x) // $ MISSING: hasValueFlow=t10.1 + } + closure1() + closure2() +} + +func t11() { + let x = source("t11.1") + let closure = { [x = x, blah = x] in + sink(x) // $ MISSING: hasValueFlow=t11.1 + sink(blah) // $ MISSING: hasValueFlow=t11.1 + } + closure() +} + +func t12() { + class Box { + var value: String + init(_ x: String) { self.value = x } + } + let x = Box(source("t12.1")) + let closure = { [weak x] in + guard let x else { return } + sink(x.value) // $ MISSING: hasValueFlow=t12.1 + } + closure() +} + +func t13() { + var x = "safe" + let closure1 = { [x] in + sink(x) // no flow + } + let closure2 = { + sink(x) // $ hasValueFlow=t13.1 + } + closure1() + closure2() + x = source("t13.1") + closure1() + closure2() +} + +class C { + var x: String + + func capture_self_by_ref() { + x = source("C.1") + let closure = { + sink(self.x) // $ hasValueFlow=C.1 + } + closure() + } + + func capture_self() { + x = source("C.2") + let closure = { [self] in + sink(self.x) // $ MISSING: hasValueFlow=C.2 + sink(x) // $ MISSING: hasValueFlow=C.2 + } + closure() + } + + func capture_weak_self() { + x = source("C.3") + let closure = { [weak self] in + guard let self else { return } + sink(self.x) // $ MISSING: hasValueFlow=C.3 + sink(x) // $ MISSING: hasValueFlow=C.3 + } + closure() + } +} diff --git a/unified/ql/test/library-tests/dataflow/test.expected b/unified/ql/test/library-tests/dataflow/test.expected index b164e3a67b2e..8a40958b3e67 100644 --- a/unified/ql/test/library-tests/dataflow/test.expected +++ b/unified/ql/test/library-tests/dataflow/test.expected @@ -80,6 +80,18 @@ edges | capture.swift:94:13:94:17 | local [x] | capture.swift:98:14:98:14 | x | provenance | | | capture.swift:94:13:94:17 | local [x] | capture.swift:99:16:99:16 | x | provenance | | | capture.swift:94:13:94:19 | local(...) | capture.swift:94:9:94:9 | y | provenance | | +| capture.swift:104:9:104:9 | x | capture.swift:105:28:105:28 | x | provenance | | +| capture.swift:104:13:104:27 | source(...) | capture.swift:104:9:104:9 | x | provenance | | +| capture.swift:105:23:105:24 | x1 | capture.swift:111:5:111:12 | closure1 [x1] | provenance | | +| capture.swift:105:28:105:28 | x | capture.swift:105:23:105:24 | x1 | provenance | | +| capture.swift:111:5:111:12 | closure1 [x1] | capture.swift:106:14:106:15 | x1 | provenance | | +| capture.swift:147:5:147:5 | x | capture.swift:149:5:149:12 | closure2 [x] | provenance | | +| capture.swift:147:9:147:23 | source(...) | capture.swift:147:5:147:5 | x | provenance | | +| capture.swift:149:5:149:12 | closure2 [x] | capture.swift:143:14:143:14 | x | provenance | | +| capture.swift:156:9:156:9 | x | capture.swift:160:9:160:15 | closure [self, x] | provenance | | +| capture.swift:156:13:156:25 | source(...) | capture.swift:156:9:156:9 | x | provenance | | +| capture.swift:158:18:158:21 | self [x] | capture.swift:158:18:158:23 | ... .x | provenance | | +| capture.swift:160:9:160:15 | closure [self, x] | capture.swift:158:18:158:21 | self [x] | provenance | | | implicit-self.swift:16:9:16:12 | [post] self [x] | implicit-self.swift:17:14:17:17 | self [x] | provenance | | | implicit-self.swift:16:9:16:14 | ... .x | implicit-self.swift:16:9:16:12 | [post] self [x] | provenance | | | implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:16:9:16:14 | ... .x | provenance | | @@ -324,6 +336,21 @@ nodes | capture.swift:95:10:95:10 | y | semmle.label | y | | capture.swift:98:14:98:14 | x | semmle.label | x | | capture.swift:99:16:99:16 | x | semmle.label | x | +| capture.swift:104:9:104:9 | x | semmle.label | x | +| capture.swift:104:13:104:27 | source(...) | semmle.label | source(...) | +| capture.swift:105:23:105:24 | x1 | semmle.label | x1 | +| capture.swift:105:28:105:28 | x | semmle.label | x | +| capture.swift:106:14:106:15 | x1 | semmle.label | x1 | +| capture.swift:111:5:111:12 | closure1 [x1] | semmle.label | closure1 [x1] | +| capture.swift:143:14:143:14 | x | semmle.label | x | +| capture.swift:147:5:147:5 | x | semmle.label | x | +| capture.swift:147:9:147:23 | source(...) | semmle.label | source(...) | +| capture.swift:149:5:149:12 | closure2 [x] | semmle.label | closure2 [x] | +| capture.swift:156:9:156:9 | x | semmle.label | x | +| capture.swift:156:13:156:25 | source(...) | semmle.label | source(...) | +| capture.swift:158:18:158:21 | self [x] | semmle.label | self [x] | +| capture.swift:158:18:158:23 | ... .x | semmle.label | ... .x | +| capture.swift:160:9:160:15 | closure [self, x] | semmle.label | closure [self, x] | | implicit-self.swift:16:9:16:12 | [post] self [x] | semmle.label | [post] self [x] | | implicit-self.swift:16:9:16:14 | ... .x | semmle.label | ... .x | | implicit-self.swift:16:18:16:31 | source(...) | semmle.label | source(...) | @@ -519,6 +546,7 @@ subpaths | capture.swift:60:13:60:13 | x | capture.swift:56:22:56:24 | arg | capture.swift:57:9:57:9 | [post] y [0] | capture.swift:61:10:61:10 | y [0] | | capture.swift:94:13:94:17 | local [x] | capture.swift:99:16:99:16 | x | capture.swift:99:16:99:16 | x | capture.swift:94:13:94:19 | local(...) | testFailures +| capture.swift:109:18:109:40 | // $ hasValueFlow=t10.1 | Missing result: hasValueFlow=t10.1 | #select | calls.swift:8:14:8:14 | x | calls.swift:10:12:10:25 | source(...) | calls.swift:8:14:8:14 | x | $@ | calls.swift:10:12:10:25 | source(...) | source(...) | | calls.swift:17:10:17:17 | target(...) | calls.swift:15:16:15:29 | source(...) | calls.swift:17:10:17:17 | target(...) | $@ | calls.swift:15:16:15:29 | source(...) | source(...) | @@ -549,6 +577,9 @@ testFailures | capture.swift:88:10:88:10 | x | capture.swift:84:13:84:26 | source(...) | capture.swift:88:10:88:10 | x | $@ | capture.swift:84:13:84:26 | source(...) | source(...) | | capture.swift:95:10:95:10 | y | capture.swift:93:13:93:26 | source(...) | capture.swift:95:10:95:10 | y | $@ | capture.swift:93:13:93:26 | source(...) | source(...) | | capture.swift:98:14:98:14 | x | capture.swift:93:13:93:26 | source(...) | capture.swift:98:14:98:14 | x | $@ | capture.swift:93:13:93:26 | source(...) | source(...) | +| capture.swift:106:14:106:15 | x1 | capture.swift:104:13:104:27 | source(...) | capture.swift:106:14:106:15 | x1 | $@ | capture.swift:104:13:104:27 | source(...) | source(...) | +| capture.swift:143:14:143:14 | x | capture.swift:147:9:147:23 | source(...) | capture.swift:143:14:143:14 | x | $@ | capture.swift:147:9:147:23 | source(...) | source(...) | +| capture.swift:158:18:158:23 | ... .x | capture.swift:156:13:156:25 | source(...) | capture.swift:158:18:158:23 | ... .x | $@ | capture.swift:156:13:156:25 | source(...) | source(...) | | implicit-self.swift:17:14:17:19 | ... .x | implicit-self.swift:16:18:16:31 | source(...) | implicit-self.swift:17:14:17:19 | ... .x | $@ | implicit-self.swift:16:18:16:31 | source(...) | source(...) | | implicit-self.swift:23:14:23:14 | x | implicit-self.swift:22:13:22:26 | source(...) | implicit-self.swift:23:14:23:14 | x | $@ | implicit-self.swift:22:13:22:26 | source(...) | source(...) | | implicit-self.swift:29:14:29:19 | ... .x | implicit-self.swift:28:13:28:26 | source(...) | implicit-self.swift:29:14:29:19 | ... .x | $@ | implicit-self.swift:28:13:28:26 | source(...) | source(...) | From a97ded057e6358bb1033b0e479f7a6ff1501fce8 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 15:33:48 +0200 Subject: [PATCH 36/40] unified: Desugar capture declaration list --- unified/extractor/src/languages/swift/swift.rs | 15 +++++++++++++-- .../closures/closure-with-capture-list.output | 6 +++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index ca80a2aaf595..c4c3761b6c25 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -795,7 +795,7 @@ fn translation_rules() -> Vec> { body: (block stmt: {body})) ), // A closure capture (`[weak self]`, `[x]`, `[y = expr]`). The optional - // ownership specifier (`weak`/`unowned`) becomes a modifier; the + // ownership specifier (`weak`/`unowned`) becomes a modifier and a unary_expr; the // captured name becomes the bound `name_node`; an explicit capture // initializer (`[y = expr]`) becomes the bound value. rule!( @@ -807,7 +807,18 @@ fn translation_rules() -> Vec> { (variable_declaration modifier: (modifier #{spec})? pattern: (identifier #{name}) - value: {val}) + value: { + // Expand [x] into [x = x] + let value = match val { + Some(val) => val, + None => tree!((identifier #{name})), + }; + // Expand [weak x] into a unary_expr, to represent the boxing in Optional.same + match spec { + Some(spec) => tree!((unary_expr operator: (prefix_operator #{spec}) operand: {value})), + None => value, + } + }) ), // A closure parameter clause (`(x: Int, y)`) unwraps to its parameters. rule!((closureParameterClause parameters: _* @params) => parameter* { params }), diff --git a/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output b/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output index a2b19c5503a7..e5f7fb03d0d5 100644 --- a/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output +++ b/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output @@ -70,9 +70,13 @@ top_level source="⟨body⟩" value: function_expr source="{ [⟨capture_declaration⟩] in ⟨body⟩ }" capture_declaration: - variable_declaration source="⟨modifier⟩ ⟨pattern⟩" + variable_declaration source="⟨modifier⟩⟨value⟩⟨pattern⟩" modifier: modifier "weak" source="weak" pattern: identifier "self" source="self" + value: + unary_expr source="⟨operator⟩ ⟨operand⟩" + operand: identifier "self" source="self" + operator: prefix_operator "weak" source="weak" body: block source="⟨stmt⟩" stmt: From 91612f2157f69da2db4d2d2b3d1b8b45d7c0f514 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Sep 2026 15:44:22 +0200 Subject: [PATCH 37/40] unified: Update test case --- unified/ql/test/library-tests/dataflow/capture.swift | 2 +- unified/ql/test/library-tests/dataflow/test.expected | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/unified/ql/test/library-tests/dataflow/capture.swift b/unified/ql/test/library-tests/dataflow/capture.swift index aabd9201e5da..c758847227d9 100644 --- a/unified/ql/test/library-tests/dataflow/capture.swift +++ b/unified/ql/test/library-tests/dataflow/capture.swift @@ -103,7 +103,7 @@ func t9() { func t10() { let x = source("t10.1") let closure1 = { [x1 = x] in - sink(x1) // $ MISSING: hasValueFlow=t10.1 + sink(x1) // $ hasValueFlow=t10.1 } let closure2 = { [x] in sink(x) // $ MISSING: hasValueFlow=t10.1 diff --git a/unified/ql/test/library-tests/dataflow/test.expected b/unified/ql/test/library-tests/dataflow/test.expected index 8a40958b3e67..6d95795fd47a 100644 --- a/unified/ql/test/library-tests/dataflow/test.expected +++ b/unified/ql/test/library-tests/dataflow/test.expected @@ -546,7 +546,6 @@ subpaths | capture.swift:60:13:60:13 | x | capture.swift:56:22:56:24 | arg | capture.swift:57:9:57:9 | [post] y [0] | capture.swift:61:10:61:10 | y [0] | | capture.swift:94:13:94:17 | local [x] | capture.swift:99:16:99:16 | x | capture.swift:99:16:99:16 | x | capture.swift:94:13:94:19 | local(...) | testFailures -| capture.swift:109:18:109:40 | // $ hasValueFlow=t10.1 | Missing result: hasValueFlow=t10.1 | #select | calls.swift:8:14:8:14 | x | calls.swift:10:12:10:25 | source(...) | calls.swift:8:14:8:14 | x | $@ | calls.swift:10:12:10:25 | source(...) | source(...) | | calls.swift:17:10:17:17 | target(...) | calls.swift:15:16:15:29 | source(...) | calls.swift:17:10:17:17 | target(...) | $@ | calls.swift:15:16:15:29 | source(...) | source(...) | From 6aeead36041219cc5664cde778651424e01ffaaa Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 1 Oct 2026 08:55:36 +0200 Subject: [PATCH 38/40] unified: Fix scoping for capture declarations --- .../unified/internal/LocalNameBinding.qll | 15 ++++-- .../test/library-tests/dataflow/capture.swift | 10 ++-- .../test/library-tests/dataflow/test.expected | 47 +++++++++++++++++++ 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll b/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll index 610742b9130d..9c3df2b1af7c 100644 --- a/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll +++ b/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll @@ -99,6 +99,16 @@ private module LocalNameBindingInput implements LocalNameBindingInputSig Date: Thu, 1 Oct 2026 09:20:54 +0200 Subject: [PATCH 39/40] unified: Simplify with getParentIndex --- .../unified/internal/LocalNameBinding.qll | 37 +------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll b/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll index 9c3df2b1af7c..62f46c8ec758 100644 --- a/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll +++ b/unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll @@ -70,45 +70,10 @@ private module LocalNameBindingInput implements LocalNameBindingInputSig Date: Thu, 1 Oct 2026 21:22:35 +0200 Subject: [PATCH 40/40] Shared: Force join order in VariableCapture --- shared/dataflow/codeql/dataflow/VariableCapture.qll | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/shared/dataflow/codeql/dataflow/VariableCapture.qll b/shared/dataflow/codeql/dataflow/VariableCapture.qll index 702e52e8e738..4b07725cd681 100644 --- a/shared/dataflow/codeql/dataflow/VariableCapture.qll +++ b/shared/dataflow/codeql/dataflow/VariableCapture.qll @@ -483,6 +483,7 @@ module Flow< } /** Gets the enclosing callable of `ce`. */ + pragma[nomagic] private Callable closureExprGetEnclosingCallable(ClosureExpr ce) { exists(BasicBlock bb | ce.hasCfgNode(bb, _) and result = bb.getEnclosingCallable()) } @@ -496,6 +497,13 @@ module Flow< ) } + /** Holds if `outer` contains or equals `inner` */ + bindingset[outer, inner] + pragma[inline_late] + private predicate isEnclosingCallable(Callable outer, Callable inner) { + outer = callableGetEnclosingCallable*(inner) + } + /** * Gets a callable that contains `ce`, or a reference to `ce` into which `ce` could be inlined without * bringing any variables out of scope. @@ -512,7 +520,7 @@ module Flow< expr.hasCfgNode(bb, _) and result = bb.getEnclosingCallable() and // The reference to `ce` is allowed to occur in a more deeply nested context - closureExprGetEnclosingCallable(ce) = callableGetEnclosingCallable*(result) + isEnclosingCallable(closureExprGetEnclosingCallable(ce), result) ) }