Skip to content

Commit cd7c851

Browse files
committed
VariableCapture: add VariableWriteSourceNode
1 parent 59de92c commit cd7c851

File tree

1 file changed

+33
-30
lines changed

1 file changed

+33
-30
lines changed

shared/dataflow/codeql/dataflow/VariableCapture.qll

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,6 @@ signature module InputSig {
9595
/** Gets the variable that is the target of this write. */
9696
CapturedVariable getVariable();
9797

98-
/** Gets the expression that is the source of this write. */
99-
Expr getSource();
100-
10198
/** Gets the location of this write. */
10299
Location getLocation();
103100

@@ -210,6 +207,22 @@ signature module OutputSig<InputSig I> {
210207
I::ClosureExpr getClosureExpr();
211208
}
212209

210+
/**
211+
* A node representing the incoming value about to be written at the given assignment.
212+
*
213+
* The captured-variable library will generate flows out of this node, and assume that other
214+
* parts of the language implementation produce the relevant data flows into this node.
215+
*
216+
* For ordinary assignments, this could be mapped to the right-hand side of the assignment.
217+
*
218+
* For more general cases, where an lvalue has no direct corresponding rvalue, this can be mapped
219+
* to a data-flow node that wraps the lvalue, with language-specific incoming data flows.
220+
*/
221+
class VariableWriteSourceNode extends ClosureNode {
222+
/** Gets the variable write for which this node is the incoming value being written to the variable. */
223+
I::VariableWrite getVariableWrite();
224+
}
225+
213226
/** Holds if `post` is a `PostUpdateNode` for `pre`. */
214227
predicate capturePostUpdateNode(SynthesizedCaptureNode post, SynthesizedCaptureNode pre);
215228

@@ -239,7 +252,6 @@ module Flow<InputSig Input> implements OutputSig<Input> {
239252
private class RelevantExpr extends FinalExpr {
240253
RelevantExpr() {
241254
this instanceof VariableRead or
242-
any(VariableWrite vw).getSource() = this or
243255
this instanceof ClosureExpr or
244256
any(ClosureExpr ce).hasAliasedAccess(this)
245257
}
@@ -353,14 +365,6 @@ module Flow<InputSig Input> implements OutputSig<Input> {
353365

354366
query predicate uniqueWriteTarget(string msg) { uniqueWriteTarget(_, msg) }
355367

356-
private predicate uniqueWriteSource(VariableWrite vw, string msg) {
357-
msg = "VariableWrite has no source expression" and not exists(vw.getSource())
358-
or
359-
msg = "VariableWrite has multiple source expressions" and 2 <= strictcount(vw.getSource())
360-
}
361-
362-
query predicate uniqueWriteSource(string msg) { uniqueWriteSource(_, msg) }
363-
364368
private predicate uniqueWriteCfgNode(VariableWrite vw, string msg) {
365369
msg = "VariableWrite has no cfg node" and not vw.hasCfgNode(_, _)
366370
or
@@ -370,17 +374,6 @@ module Flow<InputSig Input> implements OutputSig<Input> {
370374

371375
query predicate uniqueWriteCfgNode(string msg) { uniqueWriteCfgNode(_, msg) }
372376

373-
private predicate localWriteStep(VariableWrite vw, string msg) {
374-
exists(BasicBlock bb1, BasicBlock bb2 |
375-
vw.hasCfgNode(bb1, _) and
376-
vw.getSource().hasCfgNode(bb2, _) and
377-
bb1.getEnclosingCallable() != bb2.getEnclosingCallable() and
378-
msg = "VariableWrite is not a local step"
379-
)
380-
}
381-
382-
query predicate localWriteStep(string msg) { localWriteStep(_, msg) }
383-
384377
query predicate uniqueReadVariable(VariableRead vr, string msg) {
385378
msg = "VariableRead has no source variable" and not exists(vr.getVariable())
386379
or
@@ -435,9 +428,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
435428
n = strictcount(Expr e | uniqueLocation(e, msg)) or
436429
n = strictcount(Expr e | uniqueCfgNode(e, msg)) or
437430
n = strictcount(VariableWrite vw | uniqueWriteTarget(vw, msg)) or
438-
n = strictcount(VariableWrite vw | uniqueWriteSource(vw, msg)) or
439431
n = strictcount(VariableWrite vw | uniqueWriteCfgNode(vw, msg)) or
440-
n = strictcount(VariableWrite vw | localWriteStep(vw, msg)) or
441432
n = strictcount(VariableRead vr | uniqueReadVariable(vr, msg)) or
442433
n = strictcount(ClosureExpr ce | closureMustHaveBody(ce, msg)) or
443434
n = strictcount(ClosureExpr ce, Expr access | closureAliasMustBeLocal(ce, access, msg)) or
@@ -689,13 +680,12 @@ module Flow<InputSig Input> implements OutputSig<Input> {
689680
TExprNode(Expr expr, boolean isPost) {
690681
expr instanceof VariableRead and isPost = [false, true]
691682
or
692-
exists(VariableWrite vw | expr = vw.getSource() and isPost = false)
693-
or
694683
synthRead(_, _, _, _, expr) and isPost = [false, true]
695684
} or
696685
TParamNode(CapturedParameter p) or
697686
TThisParamNode(Callable c) { captureAccess(_, c) } or
698-
TMallocNode(ClosureExpr ce) { hasConstructorCapture(ce, _) }
687+
TMallocNode(ClosureExpr ce) { hasConstructorCapture(ce, _) } or
688+
TVariableWriteSourceNode(VariableWrite write)
699689

700690
class ClosureNode extends TClosureNode {
701691
/** Gets a textual representation of this node. */
@@ -721,6 +711,11 @@ module Flow<InputSig Input> implements OutputSig<Input> {
721711
result = "this" and this = TThisParamNode(_)
722712
or
723713
result = "malloc" and this = TMallocNode(_)
714+
or
715+
exists(VariableWrite write |
716+
this = TVariableWriteSourceNode(write) and
717+
result = "Source of write to " + write.getVariable().toString()
718+
)
724719
}
725720

726721
/** Gets the location of this node. */
@@ -748,6 +743,10 @@ module Flow<InputSig Input> implements OutputSig<Input> {
748743
exists(Callable c | this = TThisParamNode(c) and result = c.getLocation())
749744
or
750745
exists(ClosureExpr ce | this = TMallocNode(ce) and result = ce.getLocation())
746+
or
747+
exists(VariableWrite write |
748+
this = TVariableWriteSourceNode(write) and result = write.getLocation()
749+
)
751750
}
752751
}
753752

@@ -807,6 +806,10 @@ module Flow<InputSig Input> implements OutputSig<Input> {
807806
ClosureExpr getClosureExpr() { this = TMallocNode(result) }
808807
}
809808

809+
class VariableWriteSourceNode extends ClosureNode, TVariableWriteSourceNode {
810+
VariableWrite getVariableWrite() { this = TVariableWriteSourceNode(result) }
811+
}
812+
810813
predicate capturePostUpdateNode(SynthesizedCaptureNode post, SynthesizedCaptureNode pre) {
811814
exists(CapturedVariable v, BasicBlock bb, int i |
812815
pre = TSynthRead(v, bb, i, false) and post = TSynthRead(v, bb, i, true)
@@ -851,7 +854,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
851854
or
852855
exists(VariableWrite vw, CapturedVariable v |
853856
captureWrite(v, bb, i, true, vw) and
854-
n = TExprNode(vw.getSource(), false) and
857+
n = TVariableWriteSourceNode(vw) and
855858
isPost = false and
856859
cc = TVariable(v)
857860
)
@@ -898,7 +901,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
898901
// write to v inside the closure body
899902
exists(BasicBlock bb, int i, VariableWrite vw |
900903
captureWrite(v, bb, i, false, vw) and
901-
node1 = TExprNode(vw.getSource(), false) and
904+
node1 = TVariableWriteSourceNode(vw) and
902905
node2 = TSynthThisQualifier(bb, i, true)
903906
)
904907
}

0 commit comments

Comments
 (0)