Skip to content

Commit

Permalink
Rust: Instantiate variable capture library for data flow
Browse files Browse the repository at this point in the history
  • Loading branch information
paldepind committed Dec 11, 2024
1 parent e8357a6 commit 215922c
Show file tree
Hide file tree
Showing 6 changed files with 387 additions and 35 deletions.
60 changes: 46 additions & 14 deletions rust/ql/lib/codeql/rust/dataflow/Ssa.qll
Original file line number Diff line number Diff line change
Expand Up @@ -210,23 +210,22 @@ module Ssa {
final CfgNode getWriteAccess() { result = write }

/**
* Holds if this SSA definition assigns `value` to the underlying variable.
* Holds if this SSA definition assigns `value` to the underlying
* variable.
*
* This is either a direct assignment, `x = value`, or an assignment via
* simple pattern matching
*
* ```rb
* case value
* in Foo => x then ...
* in y => then ...
* end
* ```
* This is either the value in a direct assignment, `x = value`, or in a
* `let` statement, `let x = value`. Note that patterns on the rhs. are
* currently not supported.
*/
predicate assigns(ExprCfgNode value) {
exists(AssignmentExprCfgNode ae, BasicBlock bb, int i |
this.definesAt(_, bb, i) and
ae.getLhs() = bb.getNode(i) and
value = ae.getRhs()
exists(AssignmentExprCfgNode ae |
ae.getLhs() = write and
ae.getRhs() = value
)
or
exists(LetStmtCfgNode ls |
ls.getPat() = write and
ls.getInitializer() = value
)
}

Expand Down Expand Up @@ -338,4 +337,37 @@ module Ssa {

override Location getLocation() { result = this.getBasicBlock().getLocation() }
}

/**
* An SSA definition inserted at a call that may update the value of a captured
* variable. For example, in
*
* ```rb
* fn capture_mut() {
* let mut y = 0;
* (0..5).for_each(|| {
* y += x
* });
* y
* }
* ```
*
* a definition for `y` is inserted at the call to `for_each`.
*/
class CapturedCallDefinition extends Definition, SsaImpl::UncertainWriteDefinition {
CapturedCallDefinition() {
exists(Variable v, BasicBlock bb, int i |
this.definesAt(v, bb, i) and
SsaImpl::capturedCallWrite(_, bb, i, v)
)
}

/**
* Gets the immediately preceding definition. Since this update is uncertain,
* the value from the preceding definition might still be valid.
*/
final Definition getPriorDefinition() { result = SsaImpl::uncertainWriteDefinitionInput(this) }

override string toString() { result = "<captured exit> " + this.getSourceVariable() }
}
}
Loading

0 comments on commit 215922c

Please sign in to comment.