33 * for tracking types.
44 */
55
6- import codeql.util.Boolean
7- import codeql.util.Option
6+ private import codeql.util.Boolean
7+ private import codeql.util.Option
88
9+ /**
10+ * The step relations for type tracking.
11+ */
912signature module TypeTrackingInput {
1013 /** A node that is used by the type-trackers. */
1114 class Node {
15+ /** Gets a textual representation of this node. */
1216 string toString ( ) ;
1317 }
1418
@@ -21,6 +25,7 @@ signature module TypeTrackingInput {
2125
2226 /** A type of content to be used with the store and read steps. */
2327 class Content {
28+ /** Gets a textual representation of this content. */
2429 string toString ( ) ;
2530 }
2631
@@ -70,21 +75,21 @@ signature module TypeTrackingInput {
7075 predicate returnStep ( Node nodeFrom , LocalSourceNode nodeTo ) ;
7176
7277 /**
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
7479 * `nodeTo`.
7580 */
76- predicate storeStep ( Node nodeFrom , Node nodeTo , Content f ) ;
81+ predicate storeStep ( Node nodeFrom , Node nodeTo , Content c ) ;
7782
7883 /**
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`.
8085 */
81- predicate loadStep ( Node nodeFrom , LocalSourceNode nodeTo , Content f ) ;
86+ predicate loadStep ( Node nodeFrom , LocalSourceNode nodeTo , Content c ) ;
8287
8388 /**
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
8590 * `nodeTo`.
8691 */
87- predicate loadStoreStep ( Node nodeFrom , Node nodeTo , Content f1 , Content f2 ) ;
92+ predicate loadStoreStep ( Node nodeFrom , Node nodeTo , Content c1 , Content c2 ) ;
8893
8994 /**
9095 * Holds if type-tracking should step from `nodeFrom` to `nodeTo` if inside a
@@ -113,9 +118,14 @@ signature module TypeTrackingInput {
113118 predicate hasFeatureBacktrackStoreTarget ( ) ;
114119}
115120
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+ */
116125module TypeTracking< TypeTrackingInput I> {
117126 private import I
118127
128+ /** Provides consistency checks for the type-tracker step relations. */
119129 module ConsistencyChecks {
120130 private predicate stepEntry ( Node n , string kind ) {
121131 simpleLocalSmallStep ( n , _) and kind = "simpleLocalSmallStep"
@@ -329,12 +339,17 @@ module TypeTracking<TypeTrackingInput I> {
329339 )
330340 }
331341
342+ pragma [ inline]
343+ private predicate isLocalSourceNode ( LocalSourceNode n ) { any ( ) }
344+
332345 /**
333346 * Holds if there is flow from `localSource` to `dst` using zero or more
334347 * `simpleLocalSmallStep`s.
335348 */
336349 pragma [ nomagic]
337350 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
338353 dst = localSource
339354 or
340355 exists ( Node mid |
@@ -344,27 +359,27 @@ module TypeTracking<TypeTrackingInput I> {
344359 }
345360
346361 pragma [ nomagic]
347- private predicate storeStepIntoSource ( Node nodeFrom , LocalSourceNode nodeTo , Content f ) {
362+ private predicate storeStepIntoSource ( Node nodeFrom , LocalSourceNode nodeTo , Content c ) {
348363 if hasFeatureBacktrackStoreTarget ( )
349364 then
350365 exists ( Node obj |
351366 flowsTo ( nodeTo , obj ) and
352- storeStep ( nodeFrom , obj , f )
367+ storeStep ( nodeFrom , obj , c )
353368 )
354- else storeStep ( nodeFrom , nodeTo , f )
369+ else storeStep ( nodeFrom , nodeTo , c )
355370 }
356371
357372 pragma [ nomagic]
358373 private predicate loadStoreStepIntoSource (
359- Node nodeFrom , LocalSourceNode nodeTo , Content f1 , Content f2
374+ Node nodeFrom , LocalSourceNode nodeTo , Content c1 , Content c2
360375 ) {
361376 if hasFeatureBacktrackStoreTarget ( )
362377 then
363378 exists ( Node obj |
364379 flowsTo ( nodeTo , obj ) and
365- loadStoreStep ( nodeFrom , obj , f1 , f2 )
380+ loadStoreStep ( nodeFrom , obj , c1 , c2 )
366381 )
367- else loadStoreStep ( nodeFrom , nodeTo , f1 , f2 )
382+ else loadStoreStep ( nodeFrom , nodeTo , c1 , c2 )
368383 }
369384
370385 pragma [ nomagic]
@@ -465,8 +480,8 @@ module TypeTracking<TypeTrackingInput I> {
465480 * instead of `tt2.step`.
466481 */
467482 class TypeTracker extends TTypeTracker {
468- Boolean hasCall ;
469- ContentOption content ;
483+ private Boolean hasCall ;
484+ private ContentOption content ;
470485
471486 TypeTracker ( ) { this = MkTypeTracker ( hasCall , content ) }
472487
@@ -478,9 +493,10 @@ module TypeTracking<TypeTrackingInput I> {
478493 exists ( string withCall , string withContent |
479494 ( if hasCall = true then withCall = "with" else withCall = "without" ) and
480495 (
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 = ""
484500 ) and
485501 result = "type tracker " + withCall + " call steps" + withContent
486502 )
@@ -613,8 +629,8 @@ module TypeTracking<TypeTrackingInput I> {
613629 * instead of `t2.step`.
614630 */
615631 class TypeBackTracker extends TTypeBackTracker {
616- Boolean hasReturn ;
617- ContentOption content ;
632+ private Boolean hasReturn ;
633+ private ContentOption content ;
618634
619635 TypeBackTracker ( ) { this = MkTypeBackTracker ( hasReturn , content ) }
620636
@@ -626,9 +642,10 @@ module TypeTracking<TypeTrackingInput I> {
626642 exists ( string withReturn , string withContent |
627643 ( if hasReturn = true then withReturn = "with" else withReturn = "without" ) and
628644 (
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 = ""
632649 ) and
633650 result = "type back-tracker " + withReturn + " return steps" + withContent
634651 )
@@ -753,7 +770,7 @@ module TypeTracking<TypeTrackingInput I> {
753770 * A node on a path that is reachable from a source. This is a pair of a
754771 * `Node` and a `TypeTracker`.
755772 */
756- class PathNode extends TPathNode {
773+ class PathNodeFwd extends TPathNode {
757774 /** Gets the node of this `PathNode`. */
758775 Node getNode ( ) { this = MkPathNode ( result , _) }
759776
@@ -762,14 +779,15 @@ module TypeTracking<TypeTrackingInput I> {
762779
763780 private string ppContent ( ) {
764781 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 = ""
768786 )
769787 }
770788
771789 /** 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 ( ) }
773791
774792 /** Holds if this is a source. */
775793 predicate isSource ( ) { source ( this .getNode ( ) ) and this .getTypeTracker ( ) .start ( ) }
@@ -783,26 +801,34 @@ module TypeTracking<TypeTrackingInput I> {
783801 tt2 = tt1 .step ( n1 , n2 )
784802 }
785803
786- private predicate edgeCand ( PathNode n1 , PathNode n2 ) {
804+ private predicate edgeCand ( PathNodeFwd n1 , PathNodeFwd n2 ) {
787805 edgeCand ( n1 .getNode ( ) , n1 .getTypeTracker ( ) , n2 .getNode ( ) , n2 .getTypeTracker ( ) )
788806 }
789807
790- private predicate reachRev ( PathNode n ) {
808+ private predicate reachRev ( PathNodeFwd n ) {
791809 n .isSink ( )
792810 or
793- exists ( PathNode mid |
811+ exists ( PathNodeFwd mid |
794812 edgeCand ( n , mid ) and
795813 reachRev ( mid )
796814 )
797815 }
798816
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+
799825 /** 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 ) }
801827
802828 private predicate stepPlus ( PathNode n1 , PathNode n2 ) = fastTC( edges / 2 ) ( n1 , n2 )
803829
804830 /** Holds if there is a path between `source` and `sink`. */
805- predicate flowPair ( PathNode source , PathNode sink ) {
831+ predicate hasFlow ( PathNode source , PathNode sink ) {
806832 source .isSource ( ) and
807833 sink .isSink ( ) and
808834 ( source = sink or stepPlus ( source , sink ) )
0 commit comments