Skip to content

Commit 8aec87e

Browse files
committed
Update VariableCapture.qll
1 parent 08d44c1 commit 8aec87e

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

shared/dataflow/codeql/dataflow/VariableCapture.qll

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -391,16 +391,6 @@ module Flow<InputSig Input> implements OutputSig<Input> {
391391
msg = "ClosureExpr has no body" and not ce.hasBody(_)
392392
}
393393

394-
query predicate closureAliasMustBeLocal(ClosureExpr ce, Expr access, string msg) {
395-
exists(BasicBlock bb1, BasicBlock bb2 |
396-
ce.hasAliasedAccess(access) and
397-
ce.hasCfgNode(bb1, _) and
398-
access.hasCfgNode(bb2, _) and
399-
bb1.getEnclosingCallable() != bb2.getEnclosingCallable() and
400-
msg = "ClosureExpr has non-local alias - these are ignored"
401-
)
402-
}
403-
404394
private predicate astClosureParent(Callable closure, Callable parent) {
405395
exists(ClosureExpr ce, BasicBlock bb |
406396
ce.hasBody(closure) and ce.hasCfgNode(bb, _) and parent = bb.getEnclosingCallable()
@@ -440,7 +430,6 @@ module Flow<InputSig Input> implements OutputSig<Input> {
440430
n = strictcount(VariableWrite vw | localWriteStep(vw, msg)) or
441431
n = strictcount(VariableRead vr | uniqueReadVariable(vr, msg)) or
442432
n = strictcount(ClosureExpr ce | closureMustHaveBody(ce, msg)) or
443-
n = strictcount(ClosureExpr ce, Expr access | closureAliasMustBeLocal(ce, access, msg)) or
444433
n = strictcount(CapturedVariable v, Callable c | variableAccessAstNesting(v, c, msg)) or
445434
n = strictcount(Callable c | uniqueCallableLocation(c, msg))
446435
}
@@ -518,10 +507,42 @@ module Flow<InputSig Input> implements OutputSig<Input> {
518507
}
519508

520509
/** Gets the enclosing callable of `ce`. */
521-
private Callable closureExprGetCallable(ClosureExpr ce) {
510+
private Callable closureExprGetEnclosingCallable(ClosureExpr ce) {
522511
exists(BasicBlock bb | ce.hasCfgNode(bb, _) and result = bb.getEnclosingCallable())
523512
}
524513

514+
/** Gets the enclosing callable of `inner`. */
515+
pragma[nomagic]
516+
private Callable callableGetEnclosingCallable(Callable inner) {
517+
exists(ClosureExpr closure |
518+
closure.hasBody(inner) and
519+
result = closureExprGetEnclosingCallable(closure)
520+
)
521+
}
522+
523+
/**
524+
* Gets a callable that contains a reference to `ce` into which `ce` could be inlined without
525+
* bringing any variables out of scope.
526+
*
527+
* If `ce` was to be inlined into that reference, the resulting callable
528+
* would become the enclosing callable, and thus capture the same variables as `ce`.
529+
* In some sense, we model captured aliases as if this inlining has happened.
530+
*/
531+
private Callable closureExprGetAReferencingCallable(ClosureExpr ce) {
532+
exists(Expr expr, BasicBlock bb |
533+
ce.hasAliasedAccess(expr) and
534+
expr.hasCfgNode(bb, _) and
535+
result = bb.getEnclosingCallable() and
536+
// The reference to `ce` is allowed to occur in a more deeply nested context
537+
closureExprGetEnclosingCallable(ce) = callableGetEnclosingCallable*(result)
538+
)
539+
}
540+
541+
/** Gets a callable containing `ce` or one of its aliases. */
542+
private Callable closureExprGetCallable(ClosureExpr ce) {
543+
result = [closureExprGetEnclosingCallable(ce), closureExprGetAReferencingCallable(ce)]
544+
}
545+
525546
/**
526547
* Holds if `v` is available in `c` through capture. This can either be due to
527548
* an explicit variable reference or through the construction of a closure

0 commit comments

Comments
 (0)