Skip to content

Commit 1286235

Browse files
committed
Address review comments
1 parent b424f3f commit 1286235

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

shared/dataflow/codeql/dataflow/VariableCapture.qll

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

394+
query predicate closureAliasMustBeInSameScope(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+
not bb1.getEnclosingCallable() = callableGetEnclosingCallable*(bb2.getEnclosingCallable()) and
400+
msg =
401+
"ClosureExpr has an alias outside the scope of its enclosing callable - these are ignored"
402+
)
403+
}
404+
394405
private predicate astClosureParent(Callable closure, Callable parent) {
395406
exists(ClosureExpr ce, BasicBlock bb |
396407
ce.hasBody(closure) and ce.hasCfgNode(bb, _) and parent = bb.getEnclosingCallable()
@@ -430,6 +441,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
430441
n = strictcount(VariableWrite vw | localWriteStep(vw, msg)) or
431442
n = strictcount(VariableRead vr | uniqueReadVariable(vr, msg)) or
432443
n = strictcount(ClosureExpr ce | closureMustHaveBody(ce, msg)) or
444+
n = strictcount(ClosureExpr ce, Expr access | closureAliasMustBeInSameScope(ce, access, msg)) or
433445
n = strictcount(CapturedVariable v, Callable c | variableAccessAstNesting(v, c, msg)) or
434446
n = strictcount(Callable c | uniqueCallableLocation(c, msg))
435447
}
@@ -521,14 +533,16 @@ module Flow<InputSig Input> implements OutputSig<Input> {
521533
}
522534

523535
/**
524-
* Gets a callable that contains a reference to `ce` into which `ce` could be inlined without
536+
* Gets a callable that contains `ce`, or a reference to `ce` into which `ce` could be inlined without
525537
* bringing any variables out of scope.
526538
*
527539
* If `ce` was to be inlined into that reference, the resulting callable
528540
* would become the enclosing callable, and thus capture the same variables as `ce`.
529541
* In some sense, we model captured aliases as if this inlining has happened.
530542
*/
531543
private Callable closureExprGetAReferencingCallable(ClosureExpr ce) {
544+
result = closureExprGetEnclosingCallable(ce)
545+
or
532546
exists(Expr expr, BasicBlock bb |
533547
ce.hasAliasedAccess(expr) and
534548
expr.hasCfgNode(bb, _) and
@@ -538,11 +552,6 @@ module Flow<InputSig Input> implements OutputSig<Input> {
538552
)
539553
}
540554

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-
546555
/**
547556
* Holds if `v` is available in `c` through capture. This can either be due to
548557
* an explicit variable reference or through the construction of a closure
@@ -555,7 +564,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
555564
)
556565
or
557566
exists(ClosureExpr ce |
558-
c = closureExprGetCallable(ce) and
567+
c = closureExprGetAReferencingCallable(ce) and
559568
closureCaptures(ce, v) and
560569
c != v.getCallable()
561570
)
@@ -587,11 +596,11 @@ module Flow<InputSig Input> implements OutputSig<Input> {
587596
* precaution, even though this is expected to hold for all the given aliased
588597
* accesses.
589598
*/
590-
private predicate localClosureAccess(ClosureExpr ce, Expr access, BasicBlock bb, int i) {
599+
private predicate localOrNestedClosureAccess(ClosureExpr ce, Expr access, BasicBlock bb, int i) {
591600
ce.hasAliasedAccess(access) and
592601
access.hasCfgNode(bb, i) and
593602
pragma[only_bind_out](bb.getEnclosingCallable()) =
594-
pragma[only_bind_out](closureExprGetCallable(ce))
603+
pragma[only_bind_out](closureExprGetAReferencingCallable(ce))
595604
}
596605

597606
/**
@@ -608,7 +617,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
608617
exists(ClosureExpr ce | closureCaptures(ce, v) |
609618
ce.hasCfgNode(bb, i) and ce = closure
610619
or
611-
localClosureAccess(ce, closure, bb, i)
620+
localOrNestedClosureAccess(ce, closure, bb, i)
612621
) and
613622
if v.getCallable() != bb.getEnclosingCallable() then topScope = false else topScope = true
614623
}

0 commit comments

Comments
 (0)