3
3
* for tracking types.
4
4
*/
5
5
6
- import codeql.util.Boolean
7
- import codeql.util.Option
6
+ private import codeql.util.Boolean
7
+ private import codeql.util.Option
8
8
9
+ /**
10
+ * The step relations for type tracking.
11
+ */
9
12
signature module TypeTrackingInput {
10
13
/** A node that is used by the type-trackers. */
11
14
class Node {
15
+ /** Gets a textual representation of this node. */
12
16
string toString ( ) ;
13
17
}
14
18
@@ -21,6 +25,7 @@ signature module TypeTrackingInput {
21
25
22
26
/** A type of content to be used with the store and read steps. */
23
27
class Content {
28
+ /** Gets a textual representation of this content. */
24
29
string toString ( ) ;
25
30
}
26
31
@@ -70,21 +75,21 @@ signature module TypeTrackingInput {
70
75
predicate returnStep ( Node nodeFrom , LocalSourceNode nodeTo ) ;
71
76
72
77
/**
73
- * Holds if `nodeFrom` is being written to the content `f ` of the object in
78
+ * Holds if `nodeFrom` is being written to the content `c ` of the object in
74
79
* `nodeTo`.
75
80
*/
76
- predicate storeStep ( Node nodeFrom , Node nodeTo , Content f ) ;
81
+ predicate storeStep ( Node nodeFrom , Node nodeTo , Content c ) ;
77
82
78
83
/**
79
- * Holds if `nodeTo` is the result of accessing the content `f ` of `nodeFrom`.
84
+ * Holds if `nodeTo` is the result of accessing the content `c ` of `nodeFrom`.
80
85
*/
81
- predicate loadStep ( Node nodeFrom , LocalSourceNode nodeTo , Content f ) ;
86
+ predicate loadStep ( Node nodeFrom , LocalSourceNode nodeTo , Content c ) ;
82
87
83
88
/**
84
- * Holds if the content `f1 ` of `nodeFrom` is stored in the content `f2 ` of
89
+ * Holds if the content `c1 ` of `nodeFrom` is stored in the content `c2 ` of
85
90
* `nodeTo`.
86
91
*/
87
- predicate loadStoreStep ( Node nodeFrom , Node nodeTo , Content f1 , Content f2 ) ;
92
+ predicate loadStoreStep ( Node nodeFrom , Node nodeTo , Content c1 , Content c2 ) ;
88
93
89
94
/**
90
95
* Holds if type-tracking should step from `nodeFrom` to `nodeTo` if inside a
@@ -113,9 +118,14 @@ signature module TypeTrackingInput {
113
118
predicate hasFeatureBacktrackStoreTarget ( ) ;
114
119
}
115
120
121
+ /**
122
+ * Given a set of step relations, this module provides classes and predicates
123
+ * for simple data-flow reachability suitable for tracking types.
124
+ */
116
125
module TypeTracking< TypeTrackingInput I> {
117
126
private import I
118
127
128
+ /** Provides consistency checks for the type-tracker step relations. */
119
129
module ConsistencyChecks {
120
130
private predicate stepEntry ( Node n , string kind ) {
121
131
simpleLocalSmallStep ( n , _) and kind = "simpleLocalSmallStep"
@@ -329,12 +339,17 @@ module TypeTracking<TypeTrackingInput I> {
329
339
)
330
340
}
331
341
342
+ pragma [ inline]
343
+ private predicate isLocalSourceNode ( LocalSourceNode n ) { any ( ) }
344
+
332
345
/**
333
346
* Holds if there is flow from `localSource` to `dst` using zero or more
334
347
* `simpleLocalSmallStep`s.
335
348
*/
336
349
pragma [ nomagic]
337
350
predicate flowsTo ( LocalSourceNode localSource , Node dst ) {
351
+ // explicit type check in base case to avoid repeated type tests in recursive case
352
+ isLocalSourceNode ( localSource ) and
338
353
dst = localSource
339
354
or
340
355
exists ( Node mid |
@@ -344,27 +359,27 @@ module TypeTracking<TypeTrackingInput I> {
344
359
}
345
360
346
361
pragma [ nomagic]
347
- private predicate storeStepIntoSource ( Node nodeFrom , LocalSourceNode nodeTo , Content f ) {
362
+ private predicate storeStepIntoSource ( Node nodeFrom , LocalSourceNode nodeTo , Content c ) {
348
363
if hasFeatureBacktrackStoreTarget ( )
349
364
then
350
365
exists ( Node obj |
351
366
flowsTo ( nodeTo , obj ) and
352
- storeStep ( nodeFrom , obj , f )
367
+ storeStep ( nodeFrom , obj , c )
353
368
)
354
- else storeStep ( nodeFrom , nodeTo , f )
369
+ else storeStep ( nodeFrom , nodeTo , c )
355
370
}
356
371
357
372
pragma [ nomagic]
358
373
private predicate loadStoreStepIntoSource (
359
- Node nodeFrom , LocalSourceNode nodeTo , Content f1 , Content f2
374
+ Node nodeFrom , LocalSourceNode nodeTo , Content c1 , Content c2
360
375
) {
361
376
if hasFeatureBacktrackStoreTarget ( )
362
377
then
363
378
exists ( Node obj |
364
379
flowsTo ( nodeTo , obj ) and
365
- loadStoreStep ( nodeFrom , obj , f1 , f2 )
380
+ loadStoreStep ( nodeFrom , obj , c1 , c2 )
366
381
)
367
- else loadStoreStep ( nodeFrom , nodeTo , f1 , f2 )
382
+ else loadStoreStep ( nodeFrom , nodeTo , c1 , c2 )
368
383
}
369
384
370
385
pragma [ nomagic]
@@ -465,8 +480,8 @@ module TypeTracking<TypeTrackingInput I> {
465
480
* instead of `tt2.step`.
466
481
*/
467
482
class TypeTracker extends TTypeTracker {
468
- Boolean hasCall ;
469
- ContentOption content ;
483
+ private Boolean hasCall ;
484
+ private ContentOption content ;
470
485
471
486
TypeTracker ( ) { this = MkTypeTracker ( hasCall , content ) }
472
487
@@ -478,9 +493,10 @@ module TypeTracking<TypeTrackingInput I> {
478
493
exists ( string withCall , string withContent |
479
494
( if hasCall = true then withCall = "with" else withCall = "without" ) and
480
495
(
481
- if content instanceof ContentOption:: Some
482
- then withContent = " with content " + content .asSome ( )
483
- else withContent = ""
496
+ withContent = " with content " + content .asSome ( )
497
+ or
498
+ content instanceof ContentOption:: None and
499
+ withContent = ""
484
500
) and
485
501
result = "type tracker " + withCall + " call steps" + withContent
486
502
)
@@ -613,8 +629,8 @@ module TypeTracking<TypeTrackingInput I> {
613
629
* instead of `t2.step`.
614
630
*/
615
631
class TypeBackTracker extends TTypeBackTracker {
616
- Boolean hasReturn ;
617
- ContentOption content ;
632
+ private Boolean hasReturn ;
633
+ private ContentOption content ;
618
634
619
635
TypeBackTracker ( ) { this = MkTypeBackTracker ( hasReturn , content ) }
620
636
@@ -626,9 +642,10 @@ module TypeTracking<TypeTrackingInput I> {
626
642
exists ( string withReturn , string withContent |
627
643
( if hasReturn = true then withReturn = "with" else withReturn = "without" ) and
628
644
(
629
- if content instanceof ContentOption:: Some
630
- then withContent = " with content " + content
631
- else withContent = ""
645
+ withContent = " with content " + content .asSome ( )
646
+ or
647
+ content instanceof ContentOption:: None and
648
+ withContent = ""
632
649
) and
633
650
result = "type back-tracker " + withReturn + " return steps" + withContent
634
651
)
@@ -753,7 +770,7 @@ module TypeTracking<TypeTrackingInput I> {
753
770
* A node on a path that is reachable from a source. This is a pair of a
754
771
* `Node` and a `TypeTracker`.
755
772
*/
756
- class PathNode extends TPathNode {
773
+ class PathNodeFwd extends TPathNode {
757
774
/** Gets the node of this `PathNode`. */
758
775
Node getNode ( ) { this = MkPathNode ( result , _) }
759
776
@@ -762,14 +779,15 @@ module TypeTracking<TypeTrackingInput I> {
762
779
763
780
private string ppContent ( ) {
764
781
exists ( ContentOption c | this .getTypeTracker ( ) = MkTypeTracker ( _, c ) |
765
- if c instanceof ContentOption:: Some
766
- then result = " with content " + c .asSome ( )
767
- else result = ""
782
+ result = " with content " + c .asSome ( )
783
+ or
784
+ c instanceof ContentOption:: None and
785
+ result = ""
768
786
)
769
787
}
770
788
771
789
/** Gets a textual representation of this node. */
772
- string toString ( ) { result = this .getNode ( ) .toString ( ) + " " + this .ppContent ( ) }
790
+ string toString ( ) { result = this .getNode ( ) .toString ( ) + this .ppContent ( ) }
773
791
774
792
/** Holds if this is a source. */
775
793
predicate isSource ( ) { source ( this .getNode ( ) ) and this .getTypeTracker ( ) .start ( ) }
@@ -783,26 +801,34 @@ module TypeTracking<TypeTrackingInput I> {
783
801
tt2 = tt1 .step ( n1 , n2 )
784
802
}
785
803
786
- private predicate edgeCand ( PathNode n1 , PathNode n2 ) {
804
+ private predicate edgeCand ( PathNodeFwd n1 , PathNodeFwd n2 ) {
787
805
edgeCand ( n1 .getNode ( ) , n1 .getTypeTracker ( ) , n2 .getNode ( ) , n2 .getTypeTracker ( ) )
788
806
}
789
807
790
- private predicate reachRev ( PathNode n ) {
808
+ private predicate reachRev ( PathNodeFwd n ) {
791
809
n .isSink ( )
792
810
or
793
- exists ( PathNode mid |
811
+ exists ( PathNodeFwd mid |
794
812
edgeCand ( n , mid ) and
795
813
reachRev ( mid )
796
814
)
797
815
}
798
816
817
+ /**
818
+ * A node on a path that is reachable from a source and can reach a sink.
819
+ * This is a pair of a `Node` and a `TypeTracker`.
820
+ */
821
+ class PathNode extends PathNodeFwd {
822
+ PathNode ( ) { reachRev ( this ) }
823
+ }
824
+
799
825
/** Holds if `(p1, p2)` is an edge in a path between a source and a sink. */
800
- query predicate edges ( PathNode n1 , PathNode n2 ) { edgeCand ( n1 , n2 ) and reachRev ( n2 ) }
826
+ query predicate edges ( PathNode n1 , PathNode n2 ) { edgeCand ( n1 , n2 ) }
801
827
802
828
private predicate stepPlus ( PathNode n1 , PathNode n2 ) = fastTC( edges / 2 ) ( n1 , n2 )
803
829
804
830
/** Holds if there is a path between `source` and `sink`. */
805
- predicate flowPair ( PathNode source , PathNode sink ) {
831
+ predicate hasFlow ( PathNode source , PathNode sink ) {
806
832
source .isSource ( ) and
807
833
sink .isSink ( ) and
808
834
( source = sink or stepPlus ( source , sink ) )
0 commit comments