Skip to content

Commit 577afc3

Browse files
committed
Rust: Support capture of mutable variables in SSA
1 parent a1db359 commit 577afc3

File tree

2 files changed

+45
-15
lines changed

2 files changed

+45
-15
lines changed

rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,15 @@ module SsaInput implements SsaImplCommon::InputSig<Location> {
4949
/**
5050
* A variable amenable to SSA construction.
5151
*
52-
* All immutable variables are amenable. Mutable variables are restricted
53-
* to those that are not captured by closures, and are not borrowed
54-
* (either explicitly using `& mut`, or (potentially) implicit as borrowed
55-
* receivers in a method call).
52+
* All immutable variables are amenable. Mutable variables are restricted to
53+
* those that are not borrowed (either explicitly using `& mut`, or
54+
* (potentially) implicit as borrowed receivers in a method call).
5655
*/
5756
class SourceVariable extends Variable {
5857
SourceVariable() {
5958
this.isImmutable()
6059
or
6160
this.isMutable() and
62-
not this.isCaptured() and
6361
forall(VariableAccess va | va = this.getAnAccess() |
6462
va instanceof VariableReadAccess and
6563
// receivers can be borrowed implicitly, cf.
@@ -102,6 +100,8 @@ module SsaInput implements SsaImplCommon::InputSig<Location> {
102100
v = va.getVariable() and
103101
certain = false
104102
)
103+
or
104+
capturedExitRead(bb, i, v) and certain = false
105105
}
106106
}
107107

@@ -207,14 +207,32 @@ private predicate lastRefSkipUncertainReadsExt(DefinitionExt def, BasicBlock bb,
207207
)
208208
}
209209

210-
/** Holds if `bb` contains a captured access to variable `v`. */
210+
private VariableAccess getCapturedVariableAccess(BasicBlock bb, Variable v) {
211+
result = bb.getANode().getAstNode() and
212+
result.isCapture() and
213+
result.getVariable() = v
214+
}
215+
216+
/** Holds if `bb` contains a captured write to variable `v`. */
217+
pragma[noinline]
218+
private predicate writesCapturedVariable(BasicBlock bb, Variable v) {
219+
getCapturedVariableAccess(bb, v) instanceof VariableWriteAccess
220+
}
221+
222+
/** Holds if `bb` contains a captured read to variable `v`. */
211223
pragma[nomagic]
212-
private predicate hasCapturedVariableAccess(BasicBlock bb, Variable v) {
213-
exists(VariableAccess read |
214-
read = bb.getANode().getAstNode() and
215-
read.isCapture() and
216-
read.getVariable() = v
217-
)
224+
private predicate readsCapturedVariable(BasicBlock bb, Variable v) {
225+
getCapturedVariableAccess(bb, v) instanceof VariableReadAccess
226+
}
227+
228+
/**
229+
* Holds if a pseudo read of captured variable `v` should be inserted
230+
* at index `i` in exit block `bb`.
231+
*/
232+
private predicate capturedExitRead(AnnotatedExitBasicBlock bb, int i, Variable v) {
233+
bb.isNormal() and
234+
writesCapturedVariable(bb.getAPredecessor*(), v) and
235+
i = bb.length()
218236
}
219237

220238
cached
@@ -225,7 +243,7 @@ private module Cached {
225243
*/
226244
cached
227245
predicate capturedEntryWrite(EntryBasicBlock bb, int i, Variable v) {
228-
hasCapturedVariableAccess(bb.getASuccessor*(), v) and
246+
readsCapturedVariable(bb.getASuccessor*(), v) and
229247
i = -1
230248
}
231249

rust/ql/test/library-tests/variables/Ssa.expected

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ nonSsaVariable
55
| variables.rs:372:13:372:13 | x |
66
| variables.rs:379:13:379:13 | z |
77
| variables.rs:392:13:392:13 | x |
8-
| variables.rs:410:13:410:13 | x |
9-
| variables.rs:418:13:418:13 | y |
108
| variables.rs:426:13:426:13 | z |
119
| variables.rs:478:13:478:13 | a |
1210
| variables.rs:506:11:506:11 | a |
@@ -115,8 +113,12 @@ definition
115113
| variables.rs:400:9:400:9 | x | variables.rs:400:9:400:9 | x |
116114
| variables.rs:402:9:402:11 | cap | variables.rs:402:9:402:11 | cap |
117115
| variables.rs:402:15:404:5 | <captured entry> x | variables.rs:400:9:400:9 | x |
116+
| variables.rs:410:9:410:13 | x | variables.rs:410:13:410:13 | x |
118117
| variables.rs:412:9:412:16 | closure1 | variables.rs:412:9:412:16 | closure1 |
118+
| variables.rs:412:20:414:5 | <captured entry> x | variables.rs:410:13:410:13 | x |
119+
| variables.rs:418:9:418:13 | y | variables.rs:418:13:418:13 | y |
119120
| variables.rs:420:9:420:20 | closure2 | variables.rs:420:13:420:20 | closure2 |
121+
| variables.rs:421:9:421:9 | y | variables.rs:418:13:418:13 | y |
120122
| variables.rs:428:9:428:20 | closure3 | variables.rs:428:13:428:20 | closure3 |
121123
| variables.rs:435:8:435:8 | b | variables.rs:435:8:435:8 | b |
122124
| variables.rs:436:9:436:13 | x | variables.rs:436:13:436:13 | x |
@@ -227,7 +229,10 @@ read
227229
| variables.rs:400:9:400:9 | x | variables.rs:400:9:400:9 | x | variables.rs:406:15:406:15 | x |
228230
| variables.rs:402:9:402:11 | cap | variables.rs:402:9:402:11 | cap | variables.rs:405:5:405:7 | cap |
229231
| variables.rs:402:15:404:5 | <captured entry> x | variables.rs:400:9:400:9 | x | variables.rs:403:19:403:19 | x |
232+
| variables.rs:410:9:410:13 | x | variables.rs:410:13:410:13 | x | variables.rs:416:15:416:15 | x |
230233
| variables.rs:412:9:412:16 | closure1 | variables.rs:412:9:412:16 | closure1 | variables.rs:415:5:415:12 | closure1 |
234+
| variables.rs:412:20:414:5 | <captured entry> x | variables.rs:410:13:410:13 | x | variables.rs:413:19:413:19 | x |
235+
| variables.rs:418:9:418:13 | y | variables.rs:418:13:418:13 | y | variables.rs:424:15:424:15 | y |
231236
| variables.rs:420:9:420:20 | closure2 | variables.rs:420:13:420:20 | closure2 | variables.rs:423:5:423:12 | closure2 |
232237
| variables.rs:428:9:428:20 | closure3 | variables.rs:428:13:428:20 | closure3 | variables.rs:431:5:431:12 | closure3 |
233238
| variables.rs:435:8:435:8 | b | variables.rs:435:8:435:8 | b | variables.rs:439:8:439:8 | b |
@@ -326,7 +331,10 @@ firstRead
326331
| variables.rs:400:9:400:9 | x | variables.rs:400:9:400:9 | x | variables.rs:406:15:406:15 | x |
327332
| variables.rs:402:9:402:11 | cap | variables.rs:402:9:402:11 | cap | variables.rs:405:5:405:7 | cap |
328333
| variables.rs:402:15:404:5 | <captured entry> x | variables.rs:400:9:400:9 | x | variables.rs:403:19:403:19 | x |
334+
| variables.rs:410:9:410:13 | x | variables.rs:410:13:410:13 | x | variables.rs:416:15:416:15 | x |
329335
| variables.rs:412:9:412:16 | closure1 | variables.rs:412:9:412:16 | closure1 | variables.rs:415:5:415:12 | closure1 |
336+
| variables.rs:412:20:414:5 | <captured entry> x | variables.rs:410:13:410:13 | x | variables.rs:413:19:413:19 | x |
337+
| variables.rs:418:9:418:13 | y | variables.rs:418:13:418:13 | y | variables.rs:424:15:424:15 | y |
330338
| variables.rs:420:9:420:20 | closure2 | variables.rs:420:13:420:20 | closure2 | variables.rs:423:5:423:12 | closure2 |
331339
| variables.rs:428:9:428:20 | closure3 | variables.rs:428:13:428:20 | closure3 | variables.rs:431:5:431:12 | closure3 |
332340
| variables.rs:435:8:435:8 | b | variables.rs:435:8:435:8 | b | variables.rs:439:8:439:8 | b |
@@ -421,7 +429,10 @@ lastRead
421429
| variables.rs:400:9:400:9 | x | variables.rs:400:9:400:9 | x | variables.rs:406:15:406:15 | x |
422430
| variables.rs:402:9:402:11 | cap | variables.rs:402:9:402:11 | cap | variables.rs:405:5:405:7 | cap |
423431
| variables.rs:402:15:404:5 | <captured entry> x | variables.rs:400:9:400:9 | x | variables.rs:403:19:403:19 | x |
432+
| variables.rs:410:9:410:13 | x | variables.rs:410:13:410:13 | x | variables.rs:416:15:416:15 | x |
424433
| variables.rs:412:9:412:16 | closure1 | variables.rs:412:9:412:16 | closure1 | variables.rs:415:5:415:12 | closure1 |
434+
| variables.rs:412:20:414:5 | <captured entry> x | variables.rs:410:13:410:13 | x | variables.rs:413:19:413:19 | x |
435+
| variables.rs:418:9:418:13 | y | variables.rs:418:13:418:13 | y | variables.rs:424:15:424:15 | y |
425436
| variables.rs:420:9:420:20 | closure2 | variables.rs:420:13:420:20 | closure2 | variables.rs:423:5:423:12 | closure2 |
426437
| variables.rs:428:9:428:20 | closure3 | variables.rs:428:13:428:20 | closure3 | variables.rs:431:5:431:12 | closure3 |
427438
| variables.rs:435:8:435:8 | b | variables.rs:435:8:435:8 | b | variables.rs:439:8:439:8 | b |
@@ -531,5 +542,6 @@ ultimateDef
531542
| variables.rs:439:5:447:5 | phi | variables.rs:444:9:444:9 | x |
532543
assigns
533544
| variables.rs:23:5:23:6 | x2 | variables.rs:23:10:23:10 | 5 |
545+
| variables.rs:421:9:421:9 | y | variables.rs:421:13:421:13 | 3 |
534546
| variables.rs:440:9:440:9 | x | variables.rs:440:13:440:13 | 2 |
535547
| variables.rs:444:9:444:9 | x | variables.rs:444:13:444:13 | 3 |

0 commit comments

Comments
 (0)