@@ -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
@@ -436,9 +429,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
436
429
n = strictcount ( Expr e | uniqueLocation ( e , msg ) ) or
437
430
n = strictcount ( Expr e | uniqueCfgNode ( e , msg ) ) or
438
431
n = strictcount ( VariableWrite vw | uniqueWriteTarget ( vw , msg ) ) or
439
- n = strictcount ( VariableWrite vw | uniqueWriteSource ( vw , msg ) ) or
440
432
n = strictcount ( VariableWrite vw | uniqueWriteCfgNode ( vw , msg ) ) or
441
- n = strictcount ( VariableWrite vw | localWriteStep ( vw , msg ) ) or
442
433
n = strictcount ( VariableRead vr | uniqueReadVariable ( vr , msg ) ) or
443
434
n = strictcount ( ClosureExpr ce | closureMustHaveBody ( ce , msg ) ) or
444
435
n = strictcount ( ClosureExpr ce , Expr access | closureAliasMustBeInSameScope ( ce , access , msg ) ) or
@@ -719,13 +710,12 @@ module Flow<InputSig Input> implements OutputSig<Input> {
719
710
TExprNode ( Expr expr , boolean isPost ) {
720
711
expr instanceof VariableRead and isPost = [ false , true ]
721
712
or
722
- exists ( VariableWrite vw | expr = vw .getSource ( ) and isPost = false )
723
- or
724
713
synthRead ( _, _, _, _, expr ) and isPost = [ false , true ]
725
714
} or
726
715
TParamNode ( CapturedParameter p ) or
727
716
TThisParamNode ( Callable c ) { captureAccess ( _, c ) } or
728
- TMallocNode ( ClosureExpr ce ) { hasConstructorCapture ( ce , _) }
717
+ TMallocNode ( ClosureExpr ce ) { hasConstructorCapture ( ce , _) } or
718
+ TVariableWriteSourceNode ( VariableWrite write )
729
719
730
720
class ClosureNode extends TClosureNode {
731
721
/** Gets a textual representation of this node. */
@@ -751,6 +741,11 @@ module Flow<InputSig Input> implements OutputSig<Input> {
751
741
result = "this" and this = TThisParamNode ( _)
752
742
or
753
743
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
+ )
754
749
}
755
750
756
751
/** Gets the location of this node. */
@@ -778,6 +773,10 @@ module Flow<InputSig Input> implements OutputSig<Input> {
778
773
exists ( Callable c | this = TThisParamNode ( c ) and result = c .getLocation ( ) )
779
774
or
780
775
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
+ )
781
780
}
782
781
}
783
782
@@ -837,6 +836,10 @@ module Flow<InputSig Input> implements OutputSig<Input> {
837
836
ClosureExpr getClosureExpr ( ) { this = TMallocNode ( result ) }
838
837
}
839
838
839
+ class VariableWriteSourceNode extends ClosureNode , TVariableWriteSourceNode {
840
+ VariableWrite getVariableWrite ( ) { this = TVariableWriteSourceNode ( result ) }
841
+ }
842
+
840
843
predicate capturePostUpdateNode ( SynthesizedCaptureNode post , SynthesizedCaptureNode pre ) {
841
844
exists ( CapturedVariable v , BasicBlock bb , int i |
842
845
pre = TSynthRead ( v , bb , i , false ) and post = TSynthRead ( v , bb , i , true )
@@ -881,7 +884,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
881
884
or
882
885
exists ( VariableWrite vw , CapturedVariable v |
883
886
captureWrite ( v , bb , i , true , vw ) and
884
- n = TExprNode ( vw . getSource ( ) , false ) and
887
+ n = TVariableWriteSourceNode ( vw ) and
885
888
isPost = false and
886
889
cc = TVariable ( v )
887
890
)
@@ -928,7 +931,7 @@ module Flow<InputSig Input> implements OutputSig<Input> {
928
931
// write to v inside the closure body
929
932
exists ( BasicBlock bb , int i , VariableWrite vw |
930
933
captureWrite ( v , bb , i , false , vw ) and
931
- node1 = TExprNode ( vw . getSource ( ) , false ) and
934
+ node1 = TVariableWriteSourceNode ( vw ) and
932
935
node2 = TSynthThisQualifier ( bb , i , true )
933
936
)
934
937
}
0 commit comments