@@ -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
@@ -436,9 +429,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
436429 n = strictcount ( Expr e | uniqueLocation ( e , msg ) ) or
437430 n = strictcount ( Expr e | uniqueCfgNode ( e , msg ) ) or
438431 n = strictcount ( VariableWrite vw | uniqueWriteTarget ( vw , msg ) ) or
439- n = strictcount ( VariableWrite vw | uniqueWriteSource ( vw , msg ) ) or
440432 n = strictcount ( VariableWrite vw | uniqueWriteCfgNode ( vw , msg ) ) or
441- n = strictcount ( VariableWrite vw | localWriteStep ( vw , msg ) ) or
442433 n = strictcount ( VariableRead vr | uniqueReadVariable ( vr , msg ) ) or
443434 n = strictcount ( ClosureExpr ce | closureMustHaveBody ( ce , msg ) ) or
444435 n = strictcount ( ClosureExpr ce , Expr access | closureAliasMustBeInSameScope ( ce , access , msg ) ) or
@@ -719,13 +710,12 @@ module Flow<InputSig Input> implements OutputSig<Input> {
719710 TExprNode ( Expr expr , boolean isPost ) {
720711 expr instanceof VariableRead and isPost = [ false , true ]
721712 or
722- exists ( VariableWrite vw | expr = vw .getSource ( ) and isPost = false )
723- or
724713 synthRead ( _, _, _, _, expr ) and isPost = [ false , true ]
725714 } or
726715 TParamNode ( CapturedParameter p ) or
727716 TThisParamNode ( Callable c ) { captureAccess ( _, c ) } or
728- TMallocNode ( ClosureExpr ce ) { hasConstructorCapture ( ce , _) }
717+ TMallocNode ( ClosureExpr ce ) { hasConstructorCapture ( ce , _) } or
718+ TVariableWriteSourceNode ( VariableWrite write )
729719
730720 class ClosureNode extends TClosureNode {
731721 /** Gets a textual representation of this node. */
@@ -751,6 +741,11 @@ module Flow<InputSig Input> implements OutputSig<Input> {
751741 result = "this" and this = TThisParamNode ( _)
752742 or
753743 result = "malloc" and this = TMallocNode ( _)
744+ or
745+ exists ( VariableWrite write |
746+ this = TVariableWriteSourceNode ( write ) and
747+ result = "Source of write to " + write .getVariable ( ) .toString ( )
748+ )
754749 }
755750
756751 /** Gets the location of this node. */
@@ -778,6 +773,10 @@ module Flow<InputSig Input> implements OutputSig<Input> {
778773 exists ( Callable c | this = TThisParamNode ( c ) and result = c .getLocation ( ) )
779774 or
780775 exists ( ClosureExpr ce | this = TMallocNode ( ce ) and result = ce .getLocation ( ) )
776+ or
777+ exists ( VariableWrite write |
778+ this = TVariableWriteSourceNode ( write ) and result = write .getLocation ( )
779+ )
781780 }
782781 }
783782
@@ -837,6 +836,10 @@ module Flow<InputSig Input> implements OutputSig<Input> {
837836 ClosureExpr getClosureExpr ( ) { this = TMallocNode ( result ) }
838837 }
839838
839+ class VariableWriteSourceNode extends ClosureNode , TVariableWriteSourceNode {
840+ VariableWrite getVariableWrite ( ) { this = TVariableWriteSourceNode ( result ) }
841+ }
842+
840843 predicate capturePostUpdateNode ( SynthesizedCaptureNode post , SynthesizedCaptureNode pre ) {
841844 exists ( CapturedVariable v , BasicBlock bb , int i |
842845 pre = TSynthRead ( v , bb , i , false ) and post = TSynthRead ( v , bb , i , true )
@@ -881,7 +884,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
881884 or
882885 exists ( VariableWrite vw , CapturedVariable v |
883886 captureWrite ( v , bb , i , true , vw ) and
884- n = TExprNode ( vw . getSource ( ) , false ) and
887+ n = TVariableWriteSourceNode ( vw ) and
885888 isPost = false and
886889 cc = TVariable ( v )
887890 )
@@ -928,7 +931,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
928931 // write to v inside the closure body
929932 exists ( BasicBlock bb , int i , VariableWrite vw |
930933 captureWrite ( v , bb , i , false , vw ) and
931- node1 = TExprNode ( vw . getSource ( ) , false ) and
934+ node1 = TVariableWriteSourceNode ( vw ) and
932935 node2 = TSynthThisQualifier ( bb , i , true )
933936 )
934937 }
0 commit comments