Skip to content

Commit fdf5c84

Browse files
authored
Merge pull request #22917 from hvitved/rust/captured-flow-fixes
Rust: Fixes to flow through captured variables
2 parents d088e54 + 6afe533 commit fdf5c84

11 files changed

Lines changed: 486 additions & 258 deletions

File tree

‎rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll‎

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ private import rust
1111
private import SsaImpl as SsaImpl
1212
private import codeql.rust.controlflow.internal.Scope as Scope
1313
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
14+
private import codeql.rust.elements.internal.VariableImpl::Impl as VariableImpl
1415
private import codeql.rust.internal.PathResolution
1516
private import codeql.rust.controlflow.ControlFlowGraph
1617
private import codeql.rust.dataflow.Ssa
@@ -230,7 +231,16 @@ module LocalFlow {
230231
nodeTo.asPat() = match.getAnArm().getPat()
231232
)
232233
or
233-
nodeFrom.asExpr() = nodeTo.asExpr().(ParenExpr).getExpr()
234+
exists(ParenExpr pe, Expr e |
235+
e = pe.getExpr() and
236+
if VariableImpl::assignmentOperationDescendant(_, pe)
237+
then nodeTo.asExpr() = e and nodeFrom.asExpr() = pe
238+
else (
239+
nodeFrom.asExpr() = e and nodeTo.asExpr() = pe
240+
)
241+
)
242+
or
243+
nodeTo.asPat() = nodeFrom.asPat().(ParenPat).getPat()
234244
}
235245

236246
pragma[nomagic]
@@ -1070,43 +1080,36 @@ module VariableCapture {
10701080
final class CapturedParameter extends CapturedVariable {
10711081
ParamBase p;
10721082

1073-
CapturedParameter() { p = this.getParameter() }
1083+
CapturedParameter() { this.isParameter(p) }
10741084

10751085
SourceParameterNode getParameterNode() { result.getParameter() = p }
10761086
}
10771087

10781088
class Expr extends AstNode {
1079-
predicate hasCfgNode(BasicBlocks::BasicBlock bb, int i) { this = bb.getNode(i).getAstNode() }
1089+
predicate hasCfgNode(BasicBlocks::BasicBlock bb, int i) {
1090+
this = bb.getNode(i).getAstNode()
1091+
or
1092+
this.(ParenExpr).getExpr().(Expr).hasCfgNode(bb, i)
1093+
}
10801094
}
10811095

10821096
class VariableWrite extends Expr {
1083-
Expr source;
10841097
CapturedVariable v;
10851098

10861099
VariableWrite() {
1087-
exists(AssignmentExpr assign, Variable::VariableWriteAccess write |
1088-
this = assign and
1089-
v = write.getVariable() and
1090-
assign.getLhs() = write and
1091-
assign.getRhs() = source
1092-
)
1100+
this = v.getName()
10931101
or
1094-
this =
1095-
any(LetStmt ls |
1096-
v.getPat() = ls.getPat() and
1097-
ls.getInitializer() = source
1098-
)
1102+
v = this.(Variable::VariableWriteAccess).getVariable()
1103+
}
1104+
1105+
override predicate hasCfgNode(BasicBlocks::BasicBlock bb, int i) {
1106+
not this instanceof VariableWriteAccess and
1107+
super.hasCfgNode(bb, i)
10991108
or
1100-
this =
1101-
any(LetExpr le |
1102-
v.getPat() = le.getPat() and
1103-
le.getScrutinee() = source
1104-
)
1109+
this.(VariableWriteAccess).getAssignmentExpr() = bb.getNode(i).getAstNode()
11051110
}
11061111

11071112
CapturedVariable getVariable() { result = v }
1108-
1109-
Expr getSource() { result = source }
11101113
}
11111114

11121115
class VariableRead extends Expr {
@@ -1145,7 +1148,7 @@ module VariableCapture {
11451148
or
11461149
result.(Flow::ExprNode).getExpr() = n.asExpr()
11471150
or
1148-
result.(Flow::VariableWriteSourceNode).getVariableWrite().getSource() = n.asExpr()
1151+
result.(Flow::VariableWriteSourceNode).getVariableWrite() = n.getAstNode()
11491152
or
11501153
result.(Flow::ExprPostUpdateNode).getExpr() = n.(PostUpdateNode).getPreUpdateNode().asExpr()
11511154
or

‎rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,12 @@ module Impl {
310310
/** Holds if this variable is captured. */
311311
predicate isCaptured() { this.getAnAccess().isCapture() }
312312

313-
/** Gets the parameter that introduces this variable, if any. */
313+
/**
314+
* Gets the parameter that introduces this variable, if any.
315+
*
316+
* Note that this variable need not be a direct parameter; it could
317+
* also be introduced through a destructuring pattern.
318+
*/
314319
cached
315320
ParamBase getParameter() {
316321
CachedStage::ref() and
@@ -319,6 +324,14 @@ module Impl {
319324
result.(Param).getPat() = getAPatAncestor*(this.getPat())
320325
}
321326

327+
/** Holds if this variable corresponds directly to the parameter `p`. */
328+
predicate isParameter(ParamBase p) {
329+
CachedStage::ref() and
330+
p = this.getSelfParam()
331+
or
332+
p.(Param).getPat() = this.getPat()
333+
}
334+
322335
/** Holds if this variable is mutable. */
323336
predicate isMutable() { this.getPat().isMut() or this.getSelfParam().isMut() }
324337

‎rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2348,7 +2348,7 @@ private module Input3 implements InputSig3 {
23482348

23492349
AstNode getDefiningNode() {
23502350
result = this.asLocalVariable().getPat().getName() or
2351-
result = this.asLocalVariable().getParameter().(SelfParam) or
2351+
this.asLocalVariable().isParameter(result.(SelfParam)) or
23522352
result = this.asConst().getName() or
23532353
result = this.asStatic().getName()
23542354
}

0 commit comments

Comments
 (0)