Skip to content

Commit 34de910

Browse files
committed
unified: Handle capturing local getters/setters
This does the minimal change needed to get things working, but it's not pretty. A later commit will refactor this to have less ad-hoc logic here.
1 parent 9da580f commit 34de910

3 files changed

Lines changed: 42 additions & 3 deletions

File tree

‎unified/ql/lib/codeql/unified/internal/dataflow/CaptureSsa.qll‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ module CaptureSsaInput implements InputSig<Location, BasicBlock> {
3535
CapturedParameter() { none() }
3636
}
3737

38-
private class TExpr = TCallableNode or TLocalVariableRefNode;
38+
private class TExpr = TCallableNode or TLocalVariableRefNode or TImplicitArgumentNode;
3939

4040
private predicate isTopLevelCallable(BuilderNode callable) {
4141
callable.isCallable(any(TopLevel t))
@@ -55,6 +55,14 @@ module CaptureSsaInput implements InputSig<Location, BasicBlock> {
5555
this = TCallableNode(callable) and
5656
bb.getNode(i).injects(callable.asSourceCallable())
5757
)
58+
or
59+
// We need to associate a CFG node with the callee argument passed to a capturing getter/setter,
60+
// so it can carry captured data in and out the getter/setter.
61+
exists(DataFlowCall call | this = TImplicitArgumentNode(call, _, false) |
62+
performsVariableAccess(call.asGetterCall(), _, TRead(), bb.getNode(i))
63+
or
64+
performsVariableAccess(call.asSetterCall(), _, TWrite(), bb.getNode(i))
65+
)
5866
}
5967
}
6068

@@ -114,6 +122,19 @@ module CaptureSsaInput implements InputSig<Location, BasicBlock> {
114122
predicate hasAliasedAccess(Expr f) {
115123
// TODO: Restrict to places where the function is called or escapes into a call where it might get called.
116124
callableHasLocalAlias(callable, f) and not f.(LocalVariableRefNode).getRefKind().isWrite()
125+
or
126+
// Record the callee argument passed into a local capturing getter/setter as an alias for that getter/setter
127+
// so it can carry capture data in and out of the getter/setter call.
128+
exists(ComputedLocalVariable local, DataFlowCall call |
129+
callable = local.getAnAccessor() and
130+
f = TImplicitArgumentNode(call, any(ArgumentPosition p | p.isCallee()), false)
131+
|
132+
callable instanceof GetterDeclaration and
133+
call.asGetterCall() = local.getAnAccess()
134+
or
135+
callable instanceof SetterDeclaration and
136+
call.asSetterCall() = local.getAnAccess()
137+
)
117138
}
118139
}
119140
}

‎unified/ql/test/library-tests/dataflow/accessors_local.swift‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ func t5() {
4444
func t6() {
4545
var y: String = source("t6.1")
4646
var x: String { y }
47-
sink(x) // $ MISSING: hasValueFlow=t6.1
47+
sink(x) // $ hasValueFlow=t6.1
4848
}
4949

5050
func t7() {
5151
var y: String = "safe"
5252
var x: String { y }
5353
sink(x) // no flow
5454
y = source("t7.1")
55-
sink(x) // $ MISSING: hasValueFlow=t7.1
55+
sink(x) // $ hasValueFlow=t7.1
5656
}

‎unified/ql/test/library-tests/dataflow/test.expected‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ edges
2222
| accessors_local.swift:39:9:39:11 | newValue | accessors_local.swift:39:20:39:27 | newValue | provenance | |
2323
| accessors_local.swift:41:5:41:5 | x | accessors_local.swift:39:9:39:11 | newValue | provenance | |
2424
| accessors_local.swift:41:9:41:9 | x | accessors_local.swift:41:5:41:5 | x | provenance | |
25+
| accessors_local.swift:45:9:45:9 | y | accessors_local.swift:46:21:46:21 | y | provenance | |
26+
| accessors_local.swift:45:9:45:9 | y | accessors_local.swift:47:10:47:10 | x | provenance | |
27+
| accessors_local.swift:45:21:45:34 | source(...) | accessors_local.swift:45:9:45:9 | y | provenance | |
28+
| accessors_local.swift:54:5:54:5 | y | accessors_local.swift:52:21:52:21 | y | provenance | |
29+
| accessors_local.swift:54:5:54:5 | y | accessors_local.swift:55:10:55:10 | x | provenance | |
30+
| accessors_local.swift:54:9:54:22 | source(...) | accessors_local.swift:54:5:54:5 | y | provenance | |
2531
| accessors_static.swift:8:32:8:45 | source(...) | accessors_static.swift:10:10:10:12 | ... .x | provenance | |
2632
| accessors_static.swift:18:19:18:32 | source(...) | accessors_static.swift:21:10:21:12 | ... .x | provenance | |
2733
| accessors_static.swift:27:19:27:32 | source(...) | accessors_static.swift:31:10:31:12 | ... .x | provenance | |
@@ -527,6 +533,14 @@ nodes
527533
| accessors_local.swift:39:20:39:27 | newValue | semmle.label | newValue |
528534
| accessors_local.swift:41:5:41:5 | x | semmle.label | x |
529535
| accessors_local.swift:41:9:41:9 | x | semmle.label | x |
536+
| accessors_local.swift:45:9:45:9 | y | semmle.label | y |
537+
| accessors_local.swift:45:21:45:34 | source(...) | semmle.label | source(...) |
538+
| accessors_local.swift:46:21:46:21 | y | semmle.label | y |
539+
| accessors_local.swift:47:10:47:10 | x | semmle.label | x |
540+
| accessors_local.swift:52:21:52:21 | y | semmle.label | y |
541+
| accessors_local.swift:54:5:54:5 | y | semmle.label | y |
542+
| accessors_local.swift:54:9:54:22 | source(...) | semmle.label | source(...) |
543+
| accessors_local.swift:55:10:55:10 | x | semmle.label | x |
530544
| accessors_static.swift:8:32:8:45 | source(...) | semmle.label | source(...) |
531545
| accessors_static.swift:10:10:10:12 | ... .x | semmle.label | ... .x |
532546
| accessors_static.swift:18:19:18:32 | source(...) | semmle.label | source(...) |
@@ -1105,6 +1119,8 @@ nodes
11051119
| test.swift:273:30:273:45 | source(...) | semmle.label | source(...) |
11061120
| test.swift:274:10:274:12 | f(...) | semmle.label | f(...) |
11071121
subpaths
1122+
| accessors_local.swift:45:9:45:9 | y | accessors_local.swift:46:21:46:21 | y | accessors_local.swift:46:21:46:21 | y | accessors_local.swift:47:10:47:10 | x |
1123+
| accessors_local.swift:54:5:54:5 | y | accessors_local.swift:52:21:52:21 | y | accessors_local.swift:52:21:52:21 | y | accessors_local.swift:55:10:55:10 | x |
11081124
| 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(...) |
11091125
| 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(...) |
11101126
| 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 |
@@ -1135,6 +1151,8 @@ testFailures
11351151
| accessors_local.swift:25:10:25:10 | x | accessors_local.swift:22:15:22:28 | source(...) | accessors_local.swift:25:10:25:10 | x | $@ | accessors_local.swift:22:15:22:28 | source(...) | source(...) |
11361152
| accessors_local.swift:31:20:31:27 | newValue | accessors_local.swift:33:9:33:22 | source(...) | accessors_local.swift:31:20:31:27 | newValue | $@ | accessors_local.swift:33:9:33:22 | source(...) | source(...) |
11371153
| accessors_local.swift:39:20:39:27 | newValue | accessors_local.swift:38:15:38:28 | source(...) | accessors_local.swift:39:20:39:27 | newValue | $@ | accessors_local.swift:38:15:38:28 | source(...) | source(...) |
1154+
| accessors_local.swift:47:10:47:10 | x | accessors_local.swift:45:21:45:34 | source(...) | accessors_local.swift:47:10:47:10 | x | $@ | accessors_local.swift:45:21:45:34 | source(...) | source(...) |
1155+
| accessors_local.swift:55:10:55:10 | x | accessors_local.swift:54:9:54:22 | source(...) | accessors_local.swift:55:10:55:10 | x | $@ | accessors_local.swift:54:9:54:22 | source(...) | source(...) |
11381156
| accessors_static.swift:10:10:10:12 | ... .x | accessors_static.swift:8:32:8:45 | source(...) | accessors_static.swift:10:10:10:12 | ... .x | $@ | accessors_static.swift:8:32:8:45 | source(...) | source(...) |
11391157
| accessors_static.swift:21:10:21:12 | ... .x | accessors_static.swift:18:19:18:32 | source(...) | accessors_static.swift:21:10:21:12 | ... .x | $@ | accessors_static.swift:18:19:18:32 | source(...) | source(...) |
11401158
| accessors_static.swift:31:10:31:12 | ... .x | accessors_static.swift:27:19:27:32 | source(...) | accessors_static.swift:31:10:31:12 | ... .x | $@ | accessors_static.swift:27:19:27:32 | source(...) | source(...) |

0 commit comments

Comments
 (0)