@@ -95,9 +95,6 @@ signature module InputSig {
95
95
/** Gets the variable that is the target of this write. */
96
96
CapturedVariable getVariable ( ) ;
97
97
98
- /** Gets the expression that is the source of this write. */
99
- Expr getSource ( ) ;
100
-
101
98
/** Gets the location of this write. */
102
99
Location getLocation ( ) ;
103
100
@@ -210,6 +207,22 @@ signature module OutputSig<InputSig I> {
210
207
I:: ClosureExpr getClosureExpr ( ) ;
211
208
}
212
209
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
+
213
226
/** Holds if `post` is a `PostUpdateNode` for `pre`. */
214
227
predicate capturePostUpdateNode ( SynthesizedCaptureNode post , SynthesizedCaptureNode pre ) ;
215
228
@@ -239,7 +252,6 @@ module Flow<InputSig Input> implements OutputSig<Input> {
239
252
private class RelevantExpr extends FinalExpr {
240
253
RelevantExpr ( ) {
241
254
this instanceof VariableRead or
242
- any ( VariableWrite vw ) .getSource ( ) = this or
243
255
this instanceof ClosureExpr or
244
256
any ( ClosureExpr ce ) .hasAliasedAccess ( this )
245
257
}
@@ -353,14 +365,6 @@ module Flow<InputSig Input> implements OutputSig<Input> {
353
365
354
366
query predicate uniqueWriteTarget ( string msg ) { uniqueWriteTarget ( _, msg ) }
355
367
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
-
364
368
private predicate uniqueWriteCfgNode ( VariableWrite vw , string msg ) {
365
369
msg = "VariableWrite has no cfg node" and not vw .hasCfgNode ( _, _)
366
370
or
@@ -370,17 +374,6 @@ module Flow<InputSig Input> implements OutputSig<Input> {
370
374
371
375
query predicate uniqueWriteCfgNode ( string msg ) { uniqueWriteCfgNode ( _, msg ) }
372
376
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
-
384
377
query predicate uniqueReadVariable ( VariableRead vr , string msg ) {
385
378
msg = "VariableRead has no source variable" and not exists ( vr .getVariable ( ) )
386
379
or
@@ -435,9 +428,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
435
428
n = strictcount ( Expr e | uniqueLocation ( e , msg ) ) or
436
429
n = strictcount ( Expr e | uniqueCfgNode ( e , msg ) ) or
437
430
n = strictcount ( VariableWrite vw | uniqueWriteTarget ( vw , msg ) ) or
438
- n = strictcount ( VariableWrite vw | uniqueWriteSource ( vw , msg ) ) or
439
431
n = strictcount ( VariableWrite vw | uniqueWriteCfgNode ( vw , msg ) ) or
440
- n = strictcount ( VariableWrite vw | localWriteStep ( vw , msg ) ) or
441
432
n = strictcount ( VariableRead vr | uniqueReadVariable ( vr , msg ) ) or
442
433
n = strictcount ( ClosureExpr ce | closureMustHaveBody ( ce , msg ) ) or
443
434
n = strictcount ( ClosureExpr ce , Expr access | closureAliasMustBeLocal ( ce , access , msg ) ) or
@@ -689,13 +680,12 @@ module Flow<InputSig Input> implements OutputSig<Input> {
689
680
TExprNode ( Expr expr , boolean isPost ) {
690
681
expr instanceof VariableRead and isPost = [ false , true ]
691
682
or
692
- exists ( VariableWrite vw | expr = vw .getSource ( ) and isPost = false )
693
- or
694
683
synthRead ( _, _, _, _, expr ) and isPost = [ false , true ]
695
684
} or
696
685
TParamNode ( CapturedParameter p ) or
697
686
TThisParamNode ( Callable c ) { captureAccess ( _, c ) } or
698
- TMallocNode ( ClosureExpr ce ) { hasConstructorCapture ( ce , _) }
687
+ TMallocNode ( ClosureExpr ce ) { hasConstructorCapture ( ce , _) } or
688
+ TVariableWriteSourceNode ( VariableWrite write )
699
689
700
690
class ClosureNode extends TClosureNode {
701
691
/** Gets a textual representation of this node. */
@@ -721,6 +711,11 @@ module Flow<InputSig Input> implements OutputSig<Input> {
721
711
result = "this" and this = TThisParamNode ( _)
722
712
or
723
713
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
+ )
724
719
}
725
720
726
721
/** Gets the location of this node. */
@@ -748,6 +743,10 @@ module Flow<InputSig Input> implements OutputSig<Input> {
748
743
exists ( Callable c | this = TThisParamNode ( c ) and result = c .getLocation ( ) )
749
744
or
750
745
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
+ )
751
750
}
752
751
}
753
752
@@ -807,6 +806,10 @@ module Flow<InputSig Input> implements OutputSig<Input> {
807
806
ClosureExpr getClosureExpr ( ) { this = TMallocNode ( result ) }
808
807
}
809
808
809
+ class VariableWriteSourceNode extends ClosureNode , TVariableWriteSourceNode {
810
+ VariableWrite getVariableWrite ( ) { this = TVariableWriteSourceNode ( result ) }
811
+ }
812
+
810
813
predicate capturePostUpdateNode ( SynthesizedCaptureNode post , SynthesizedCaptureNode pre ) {
811
814
exists ( CapturedVariable v , BasicBlock bb , int i |
812
815
pre = TSynthRead ( v , bb , i , false ) and post = TSynthRead ( v , bb , i , true )
@@ -851,7 +854,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
851
854
or
852
855
exists ( VariableWrite vw , CapturedVariable v |
853
856
captureWrite ( v , bb , i , true , vw ) and
854
- n = TExprNode ( vw . getSource ( ) , false ) and
857
+ n = TVariableWriteSourceNode ( vw ) and
855
858
isPost = false and
856
859
cc = TVariable ( v )
857
860
)
@@ -898,7 +901,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
898
901
// write to v inside the closure body
899
902
exists ( BasicBlock bb , int i , VariableWrite vw |
900
903
captureWrite ( v , bb , i , false , vw ) and
901
- node1 = TExprNode ( vw . getSource ( ) , false ) and
904
+ node1 = TVariableWriteSourceNode ( vw ) and
902
905
node2 = TSynthThisQualifier ( bb , i , true )
903
906
)
904
907
}
0 commit comments