@@ -9,7 +9,6 @@ import cpp
9
9
import semmle.code.cpp.security.Security
10
10
private import semmle.code.cpp.ir.dataflow.DataFlow
11
11
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
12
- private import semmle.code.cpp.ir.dataflow.DataFlow3
13
12
private import semmle.code.cpp.ir.IR
14
13
private import semmle.code.cpp.ir.dataflow.ResolveCall
15
14
private import semmle.code.cpp.controlflow.IRGuards
@@ -90,65 +89,64 @@ private predicate conflatePointerAndPointee(DataFlow::Node nodeFrom, DataFlow::N
90
89
)
91
90
}
92
91
93
- private class DefaultTaintTrackingCfg extends TaintTracking :: Configuration {
94
- DefaultTaintTrackingCfg ( ) { this = "DefaultTaintTrackingCfg" }
92
+ private module DefaultTaintTrackingConfig implements DataFlow :: ConfigSig {
93
+ predicate isSource ( DataFlow :: Node source ) { source = getNodeForSource ( _ ) }
95
94
96
- override predicate isSource ( DataFlow:: Node source ) { source = getNodeForSource ( _ ) }
95
+ predicate isSink ( DataFlow:: Node sink ) { exists ( adjustedSink ( sink ) ) }
97
96
98
- override predicate isSink ( DataFlow:: Node sink ) { exists ( adjustedSink ( sink ) ) }
97
+ predicate isBarrier ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
99
98
100
- override predicate isSanitizer ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
99
+ predicate isBarrierIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
101
100
102
- override predicate isSanitizerIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
103
-
104
- override predicate isAdditionalTaintStep ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
101
+ predicate isAdditionalFlowStep ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
105
102
conflatePointerAndPointee ( nodeFrom , nodeTo )
106
103
}
107
104
}
108
105
109
- private class ToGlobalVarTaintTrackingCfg extends TaintTracking:: Configuration {
110
- ToGlobalVarTaintTrackingCfg ( ) { this = "GlobalVarTaintTrackingCfg" }
106
+ private module DefaultTaintTrackingFlow = TaintTracking:: Make< DefaultTaintTrackingConfig > ;
111
107
112
- override predicate isSource ( DataFlow:: Node source ) { source = getNodeForSource ( _) }
108
+ private module ToGlobalVarTaintTrackingConfig implements DataFlow:: ConfigSig {
109
+ predicate isSource ( DataFlow:: Node source ) { source = getNodeForSource ( _) }
113
110
114
- override predicate isSink ( DataFlow:: Node sink ) {
115
- sink .asVariable ( ) instanceof GlobalOrNamespaceVariable
116
- }
111
+ predicate isSink ( DataFlow:: Node sink ) { sink .asVariable ( ) instanceof GlobalOrNamespaceVariable }
117
112
118
- override predicate isAdditionalTaintStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
113
+ predicate isAdditionalFlowStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
119
114
writesVariable ( n1 .asInstruction ( ) , n2 .asVariable ( ) .( GlobalOrNamespaceVariable ) )
120
115
or
121
116
readsVariable ( n2 .asInstruction ( ) , n1 .asVariable ( ) .( GlobalOrNamespaceVariable ) )
122
117
}
123
118
124
- override predicate isSanitizer ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
119
+ predicate isBarrier ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
125
120
126
- override predicate isSanitizerIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
121
+ predicate isBarrierIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
127
122
}
128
123
129
- private class FromGlobalVarTaintTrackingCfg extends TaintTracking2:: Configuration {
130
- FromGlobalVarTaintTrackingCfg ( ) { this = "FromGlobalVarTaintTrackingCfg" }
124
+ private module ToGlobalVarTaintTrackingFlow = TaintTracking:: Make< ToGlobalVarTaintTrackingConfig > ;
131
125
132
- override predicate isSource ( DataFlow:: Node source ) {
126
+ private module FromGlobalVarTaintTrackingConfig implements DataFlow:: ConfigSig {
127
+ predicate isSource ( DataFlow:: Node source ) {
133
128
// This set of sources should be reasonably small, which is good for
134
129
// performance since the set of sinks is very large.
135
- exists ( ToGlobalVarTaintTrackingCfg otherCfg | otherCfg . hasFlowTo ( source ) )
130
+ ToGlobalVarTaintTrackingFlow :: hasFlowTo ( source )
136
131
}
137
132
138
- override predicate isSink ( DataFlow:: Node sink ) { exists ( adjustedSink ( sink ) ) }
133
+ predicate isSink ( DataFlow:: Node sink ) { exists ( adjustedSink ( sink ) ) }
139
134
140
- override predicate isAdditionalTaintStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
135
+ predicate isAdditionalFlowStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
141
136
// Additional step for flow out of variables. There is no flow _into_
142
137
// variables in this configuration, so this step only serves to take flow
143
138
// out of a variable that's a source.
144
139
readsVariable ( n2 .asInstruction ( ) , n1 .asVariable ( ) )
145
140
}
146
141
147
- override predicate isSanitizer ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
142
+ predicate isBarrier ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
148
143
149
- override predicate isSanitizerIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
144
+ predicate isBarrierIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
150
145
}
151
146
147
+ private module FromGlobalVarTaintTrackingFlow =
148
+ TaintTracking:: Make< FromGlobalVarTaintTrackingConfig > ;
149
+
152
150
private predicate readsVariable ( LoadInstruction load , Variable var ) {
153
151
load .getSourceAddress ( ) .( VariableAddressInstruction ) .getAstVariable ( ) = var
154
152
}
@@ -332,8 +330,8 @@ private import Cached
332
330
*/
333
331
cached
334
332
predicate tainted ( Expr source , Element tainted ) {
335
- exists ( DefaultTaintTrackingCfg cfg , DataFlow:: Node sink |
336
- cfg . hasFlow ( getNodeForSource ( source ) , sink ) and
333
+ exists ( DataFlow:: Node sink |
334
+ DefaultTaintTrackingFlow :: hasFlow ( getNodeForSource ( source ) , sink ) and
337
335
tainted = adjustedSink ( sink )
338
336
)
339
337
}
@@ -359,12 +357,11 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
359
357
globalVar = ""
360
358
or
361
359
exists (
362
- ToGlobalVarTaintTrackingCfg toCfg , FromGlobalVarTaintTrackingCfg fromCfg ,
363
360
DataFlow:: VariableNode variableNode , GlobalOrNamespaceVariable global , DataFlow:: Node sink
364
361
|
365
362
global = variableNode .getVariable ( ) and
366
- toCfg . hasFlow ( getNodeForSource ( source ) , variableNode ) and
367
- fromCfg . hasFlow ( variableNode , sink ) and
363
+ ToGlobalVarTaintTrackingFlow :: hasFlow ( getNodeForSource ( source ) , variableNode ) and
364
+ FromGlobalVarTaintTrackingFlow :: hasFlow ( variableNode , sink ) and
368
365
tainted = adjustedSink ( sink ) and
369
366
global = globalVarFromId ( globalVar )
370
367
)
@@ -422,20 +419,18 @@ module TaintedWithPath {
422
419
string toString ( ) { result = "TaintTrackingConfiguration" }
423
420
}
424
421
425
- private class AdjustedConfiguration extends TaintTracking3:: Configuration {
426
- AdjustedConfiguration ( ) { this = "AdjustedConfiguration" }
427
-
428
- override predicate isSource ( DataFlow:: Node source ) {
422
+ private module AdjustedConfig implements DataFlow:: ConfigSig {
423
+ predicate isSource ( DataFlow:: Node source ) {
429
424
exists ( TaintTrackingConfiguration cfg , Expr e |
430
425
cfg .isSource ( e ) and source = getNodeForExpr ( e )
431
426
)
432
427
}
433
428
434
- override predicate isSink ( DataFlow:: Node sink ) {
429
+ predicate isSink ( DataFlow:: Node sink ) {
435
430
exists ( TaintTrackingConfiguration cfg | cfg .isSink ( adjustedSink ( sink ) ) )
436
431
}
437
432
438
- override predicate isAdditionalTaintStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
433
+ predicate isAdditionalFlowStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
439
434
conflatePointerAndPointee ( n1 , n2 )
440
435
or
441
436
// Steps into and out of global variables
@@ -448,13 +443,15 @@ module TaintedWithPath {
448
443
additionalTaintStep ( n1 , n2 )
449
444
}
450
445
451
- override predicate isSanitizer ( DataFlow:: Node node ) {
446
+ predicate isBarrier ( DataFlow:: Node node ) {
452
447
exists ( TaintTrackingConfiguration cfg , Expr e | cfg .isBarrier ( e ) and node = getNodeForExpr ( e ) )
453
448
}
454
449
455
- override predicate isSanitizerIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
450
+ predicate isBarrierIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
456
451
}
457
452
453
+ private module AdjustedFlow = TaintTracking:: Make< AdjustedConfig > ;
454
+
458
455
/*
459
456
* A sink `Element` may map to multiple `DataFlowX::PathNode`s via (the
460
457
* inverse of) `adjustedSink`. For example, an `Expr` maps to all its
@@ -470,12 +467,12 @@ module TaintedWithPath {
470
467
*/
471
468
472
469
private newtype TPathNode =
473
- TWrapPathNode ( DataFlow3 :: PathNode n ) or
470
+ TWrapPathNode ( AdjustedFlow :: PathNode n ) or
474
471
// There's a single newtype constructor for both sources and sinks since
475
472
// that makes it easiest to deal with the case where source = sink.
476
473
TEndpointPathNode ( Element e ) {
477
- exists ( AdjustedConfiguration cfg , DataFlow3 :: Node sourceNode , DataFlow3 :: Node sinkNode |
478
- cfg . hasFlow ( sourceNode , sinkNode )
474
+ exists ( DataFlow :: Node sourceNode , DataFlow :: Node sinkNode |
475
+ AdjustedFlow :: hasFlow ( sourceNode , sinkNode )
479
476
|
480
477
sourceNode = getNodeForExpr ( e ) and
481
478
exists ( TaintTrackingConfiguration ttCfg | ttCfg .isSource ( e ) )
@@ -524,7 +521,7 @@ module TaintedWithPath {
524
521
}
525
522
526
523
private class WrapPathNode extends PathNode , TWrapPathNode {
527
- DataFlow3 :: PathNode inner ( ) { this = TWrapPathNode ( result ) }
524
+ AdjustedFlow :: PathNode inner ( ) { this = TWrapPathNode ( result ) }
528
525
529
526
override string toString ( ) { result = this .inner ( ) .toString ( ) }
530
527
@@ -561,25 +558,25 @@ module TaintedWithPath {
561
558
562
559
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
563
560
query predicate edges ( PathNode a , PathNode b ) {
564
- DataFlow3 :: PathGraph:: edges ( a .( WrapPathNode ) .inner ( ) , b .( WrapPathNode ) .inner ( ) )
561
+ AdjustedFlow :: PathGraph:: edges ( a .( WrapPathNode ) .inner ( ) , b .( WrapPathNode ) .inner ( ) )
565
562
or
566
563
// To avoid showing trivial-looking steps, we _replace_ the last node instead
567
564
// of adding an edge out of it.
568
565
exists ( WrapPathNode sinkNode |
569
- DataFlow3 :: PathGraph:: edges ( a .( WrapPathNode ) .inner ( ) , sinkNode .inner ( ) ) and
566
+ AdjustedFlow :: PathGraph:: edges ( a .( WrapPathNode ) .inner ( ) , sinkNode .inner ( ) ) and
570
567
b .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
571
568
)
572
569
or
573
570
// Same for the first node
574
571
exists ( WrapPathNode sourceNode |
575
- DataFlow3 :: PathGraph:: edges ( sourceNode .inner ( ) , b .( WrapPathNode ) .inner ( ) ) and
572
+ AdjustedFlow :: PathGraph:: edges ( sourceNode .inner ( ) , b .( WrapPathNode ) .inner ( ) ) and
576
573
sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( a .( InitialPathNode ) .inner ( ) )
577
574
)
578
575
or
579
576
// Finally, handle the case where the path goes directly from a source to a
580
577
// sink, meaning that they both need to be translated.
581
578
exists ( WrapPathNode sinkNode , WrapPathNode sourceNode |
582
- DataFlow3 :: PathGraph:: edges ( sourceNode .inner ( ) , sinkNode .inner ( ) ) and
579
+ AdjustedFlow :: PathGraph:: edges ( sourceNode .inner ( ) , sinkNode .inner ( ) ) and
583
580
sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( a .( InitialPathNode ) .inner ( ) ) and
584
581
b .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
585
582
)
@@ -590,28 +587,28 @@ module TaintedWithPath {
590
587
* from `par` to `ret` within it, in the graph of data flow path explanations.
591
588
*/
592
589
query predicate subpaths ( PathNode arg , PathNode par , PathNode ret , PathNode out ) {
593
- DataFlow3 :: PathGraph:: subpaths ( arg .( WrapPathNode ) .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
590
+ AdjustedFlow :: PathGraph:: subpaths ( arg .( WrapPathNode ) .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
594
591
ret .( WrapPathNode ) .inner ( ) , out .( WrapPathNode ) .inner ( ) )
595
592
or
596
593
// To avoid showing trivial-looking steps, we _replace_ the last node instead
597
594
// of adding an edge out of it.
598
595
exists ( WrapPathNode sinkNode |
599
- DataFlow3 :: PathGraph:: subpaths ( arg .( WrapPathNode ) .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
596
+ AdjustedFlow :: PathGraph:: subpaths ( arg .( WrapPathNode ) .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
600
597
ret .( WrapPathNode ) .inner ( ) , sinkNode .inner ( ) ) and
601
598
out .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
602
599
)
603
600
or
604
601
// Same for the first node
605
602
exists ( WrapPathNode sourceNode |
606
- DataFlow3 :: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
603
+ AdjustedFlow :: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
607
604
ret .( WrapPathNode ) .inner ( ) , out .( WrapPathNode ) .inner ( ) ) and
608
605
sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( arg .( InitialPathNode ) .inner ( ) )
609
606
)
610
607
or
611
608
// Finally, handle the case where the path goes directly from a source to a
612
609
// sink, meaning that they both need to be translated.
613
610
exists ( WrapPathNode sinkNode , WrapPathNode sourceNode |
614
- DataFlow3 :: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
611
+ AdjustedFlow :: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
615
612
ret .( WrapPathNode ) .inner ( ) , sinkNode .inner ( ) ) and
616
613
sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( arg .( InitialPathNode ) .inner ( ) ) and
617
614
out .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
@@ -634,10 +631,10 @@ module TaintedWithPath {
634
631
* the computation.
635
632
*/
636
633
predicate taintedWithPath ( Expr source , Element tainted , PathNode sourceNode , PathNode sinkNode ) {
637
- exists ( AdjustedConfiguration cfg , DataFlow3 :: Node flowSource , DataFlow3 :: Node flowSink |
634
+ exists ( DataFlow :: Node flowSource , DataFlow :: Node flowSink |
638
635
source = sourceNode .( InitialPathNode ) .inner ( ) and
639
636
flowSource = getNodeForExpr ( source ) and
640
- cfg . hasFlow ( flowSource , flowSink ) and
637
+ AdjustedFlow :: hasFlow ( flowSource , flowSink ) and
641
638
tainted = adjustedSink ( flowSink ) and
642
639
tainted = sinkNode .( FinalPathNode ) .inner ( )
643
640
)
@@ -660,8 +657,8 @@ module TaintedWithPath {
660
657
* through a global variable.
661
658
*/
662
659
predicate taintedWithoutGlobals ( Element tainted ) {
663
- exists ( AdjustedConfiguration cfg , PathNode sourceNode , FinalPathNode sinkNode |
664
- cfg . isSource ( sourceNode .( WrapPathNode ) .inner ( ) .getNode ( ) ) and
660
+ exists ( PathNode sourceNode , FinalPathNode sinkNode |
661
+ AdjustedConfig :: isSource ( sourceNode .( WrapPathNode ) .inner ( ) .getNode ( ) ) and
665
662
edgesWithoutGlobals + ( sourceNode , sinkNode ) and
666
663
tainted = sinkNode .inner ( )
667
664
)
0 commit comments