@@ -106,7 +106,11 @@ private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) {
106
106
}
107
107
108
108
/** Holds if there is a level step from `nodeFrom` to `nodeTo`. */
109
- predicate levelStep ( Node nodeFrom , Node nodeTo ) { summarizedLocalStep ( nodeFrom , nodeTo ) }
109
+ predicate levelStep ( Node nodeFrom , Node nodeTo ) {
110
+ summarizedLocalStep ( nodeFrom , nodeTo )
111
+ or
112
+ TypeTrackingStep:: step ( nodeFrom , nodeTo )
113
+ }
110
114
111
115
pragma [ noinline]
112
116
private predicate argumentPositionMatch (
@@ -235,6 +239,8 @@ predicate basicStoreStep(Node nodeFrom, Node nodeTo, DataFlow::ContentSet conten
235
239
not exists ( pair .getKey ( ) .getConstantValue ( ) ) and
236
240
contents .isAnyElement ( )
237
241
)
242
+ or
243
+ TypeTrackingStep:: storeStep ( nodeFrom , nodeTo , contents )
238
244
}
239
245
240
246
private predicate hashLiteralStore ( DataFlow:: CallNode hashCreation , DataFlow:: Node argument ) {
@@ -280,6 +286,8 @@ predicate basicLoadStep(Node nodeFrom, Node nodeTo, DataFlow::ContentSet content
280
286
nodeFrom = evaluateSummaryComponentStackLocal ( callable , call , input ) and
281
287
nodeTo = evaluateSummaryComponentStackLocal ( callable , call , output )
282
288
)
289
+ or
290
+ TypeTrackingStep:: loadStep ( nodeFrom , nodeTo , contents )
283
291
}
284
292
285
293
/**
@@ -298,6 +306,8 @@ predicate basicLoadStoreStep(
298
306
nodeFrom = evaluateSummaryComponentStackLocal ( callable , call , input ) and
299
307
nodeTo = evaluateSummaryComponentStackLocal ( callable , call , output )
300
308
)
309
+ or
310
+ TypeTrackingStep:: loadStoreStep ( nodeFrom , nodeTo , loadContent , storeContent )
301
311
}
302
312
303
313
/**
@@ -314,6 +324,8 @@ predicate basicWithoutContentStep(Node nodeFrom, Node nodeTo, ContentFilter filt
314
324
nodeFrom = evaluateSummaryComponentStackLocal ( callable , call , input ) and
315
325
nodeTo = evaluateSummaryComponentStackLocal ( callable , call , output )
316
326
)
327
+ or
328
+ TypeTrackingStep:: withoutContentStep ( nodeFrom , nodeTo , filter )
317
329
}
318
330
319
331
/**
@@ -338,6 +350,8 @@ predicate basicWithContentStep(Node nodeFrom, Node nodeTo, ContentFilter filter)
338
350
nodeFrom .asExpr ( ) = node .asExpr ( ) .( Cfg:: CfgNodes:: ExprNodes:: UnaryOperationCfgNode ) .getOperand ( ) and
339
351
filter = MkElementFilter ( )
340
352
)
353
+ or
354
+ TypeTrackingStep:: withContentStep ( nodeFrom , nodeTo , filter )
341
355
}
342
356
343
357
/**
@@ -562,3 +576,100 @@ private DataFlow::Node evaluateSummaryComponentStackLocal(
562
576
)
563
577
)
564
578
}
579
+
580
+ private newtype TUnit = MkUnit ( )
581
+
582
+ /**
583
+ * A data flow edge that should be followed by type tracking.
584
+ *
585
+ * This type of edge does not affect the local data flow graph, and is not used by data-flow configurations.
586
+ *
587
+ * Note: For performance reasons, all subclasses of this class should be part
588
+ * of the standard library, and their implementations may not depend on API graphs.
589
+ * For query-specific steps, consider including the custom steps in the type-tracking predicate itself.
590
+ */
591
+ class TypeTrackingStep extends TUnit {
592
+ /** Gets the string `"unit"`. */
593
+ string toString ( ) { result = "unit" }
594
+
595
+ /**
596
+ * Holds if type-tracking should step from `pred` to `succ`.
597
+ */
598
+ predicate step ( Node pred , Node succ ) { none ( ) }
599
+
600
+ /**
601
+ * Holds if type-tracking should step from `pred` into the `content` of `succ`.
602
+ */
603
+ predicate storeStep ( Node pred , TypeTrackingNode succ , TypeTrackerContent content ) { none ( ) }
604
+
605
+ /**
606
+ * Holds if type-tracking should step from the `content` of `pred` to `succ`.
607
+ */
608
+ predicate loadStep ( Node pred , Node succ , TypeTrackerContent content ) { none ( ) }
609
+
610
+ /**
611
+ * Holds if type-tracking should step from the `loadContent` of `pred` to the `storeContent` in `succ`.
612
+ */
613
+ predicate loadStoreStep (
614
+ Node pred , TypeTrackingNode succ , TypeTrackerContent loadContent ,
615
+ TypeTrackerContent storeContent
616
+ ) {
617
+ none ( )
618
+ }
619
+
620
+ /**
621
+ * Holds if type-tracking should step from `pred` to `succ` but block flow of contents matched by `filter` through here.
622
+ */
623
+ predicate withoutContentStep ( Node pred , Node succ , ContentFilter filter ) { none ( ) }
624
+
625
+ /**
626
+ * Holds if type-tracking should step from `pred` to `succ` if inside a content matched by `filter`.
627
+ */
628
+ predicate withContentStep ( Node pred , Node succ , ContentFilter filter ) { none ( ) }
629
+ }
630
+
631
+ /** Provides access to the steps contributed by subclasses of `SharedTypeTrackingStep`. */
632
+ module TypeTrackingStep {
633
+ /**
634
+ * Holds if type-tracking should step from `pred` to `succ`.
635
+ */
636
+ predicate step ( Node pred , Node succ ) { any ( TypeTrackingStep st ) .step ( pred , succ ) }
637
+
638
+ /**
639
+ * Holds if type-tracking should step from `pred` into the `content` of `succ`.
640
+ */
641
+ predicate storeStep ( Node pred , TypeTrackingNode succ , TypeTrackerContent content ) {
642
+ any ( TypeTrackingStep st ) .storeStep ( pred , succ , content )
643
+ }
644
+
645
+ /**
646
+ * Holds if type-tracking should step from the `content` of `pred` to `succ`.
647
+ */
648
+ predicate loadStep ( Node pred , Node succ , TypeTrackerContent content ) {
649
+ any ( TypeTrackingStep st ) .loadStep ( pred , succ , content )
650
+ }
651
+
652
+ /**
653
+ * Holds if type-tracking should step from the `loadContent` of `pred` to the `storeContent` in `succ`.
654
+ */
655
+ predicate loadStoreStep (
656
+ Node pred , TypeTrackingNode succ , TypeTrackerContent loadContent ,
657
+ TypeTrackerContent storeContent
658
+ ) {
659
+ any ( TypeTrackingStep st ) .loadStoreStep ( pred , succ , loadContent , storeContent )
660
+ }
661
+
662
+ /**
663
+ * Holds if type-tracking should step from `pred` to `succ` but block flow of contents matched by `filter` through here.
664
+ */
665
+ predicate withoutContentStep ( Node pred , Node succ , ContentFilter filter ) {
666
+ any ( TypeTrackingStep st ) .withoutContentStep ( pred , succ , filter )
667
+ }
668
+
669
+ /**
670
+ * Holds if type-tracking should step from `pred` to `succ` if inside a content matched by `filter`.
671
+ */
672
+ predicate withContentStep ( Node pred , Node succ , ContentFilter filter ) {
673
+ any ( TypeTrackingStep st ) .withContentStep ( pred , succ , filter )
674
+ }
675
+ }
0 commit comments