@@ -9,7 +9,6 @@ import cpp
99import semmle.code.cpp.security.Security
1010private import semmle.code.cpp.ir.dataflow.DataFlow
1111private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
12- private import semmle.code.cpp.ir.dataflow.DataFlow3
1312private import semmle.code.cpp.ir.IR
1413private import semmle.code.cpp.ir.dataflow.ResolveCall
1514private import semmle.code.cpp.controlflow.IRGuards
@@ -90,65 +89,64 @@ private predicate conflatePointerAndPointee(DataFlow::Node nodeFrom, DataFlow::N
9089 )
9190}
9291
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 ( _ ) }
9594
96- override predicate isSource ( DataFlow:: Node source ) { source = getNodeForSource ( _ ) }
95+ predicate isSink ( DataFlow:: Node sink ) { exists ( adjustedSink ( sink ) ) }
9796
98- override predicate isSink ( DataFlow:: Node sink ) { exists ( adjustedSink ( sink ) ) }
97+ predicate isBarrier ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
9998
100- override predicate isSanitizer ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
99+ predicate isBarrierIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
101100
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 ) {
105102 conflatePointerAndPointee ( nodeFrom , nodeTo )
106103 }
107104}
108105
109- private class ToGlobalVarTaintTrackingCfg extends TaintTracking:: Configuration {
110- ToGlobalVarTaintTrackingCfg ( ) { this = "GlobalVarTaintTrackingCfg" }
106+ private module DefaultTaintTrackingFlow = TaintTracking:: Make< DefaultTaintTrackingConfig > ;
111107
112- override predicate isSource ( DataFlow:: Node source ) { source = getNodeForSource ( _) }
108+ private module ToGlobalVarTaintTrackingConfig implements DataFlow:: ConfigSig {
109+ predicate isSource ( DataFlow:: Node source ) { source = getNodeForSource ( _) }
113110
114- override predicate isSink ( DataFlow:: Node sink ) {
115- sink .asVariable ( ) instanceof GlobalOrNamespaceVariable
116- }
111+ predicate isSink ( DataFlow:: Node sink ) { sink .asVariable ( ) instanceof GlobalOrNamespaceVariable }
117112
118- override predicate isAdditionalTaintStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
113+ predicate isAdditionalFlowStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
119114 writesVariable ( n1 .asInstruction ( ) , n2 .asVariable ( ) .( GlobalOrNamespaceVariable ) )
120115 or
121116 readsVariable ( n2 .asInstruction ( ) , n1 .asVariable ( ) .( GlobalOrNamespaceVariable ) )
122117 }
123118
124- override predicate isSanitizer ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
119+ predicate isBarrier ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
125120
126- override predicate isSanitizerIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
121+ predicate isBarrierIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
127122}
128123
129- private class FromGlobalVarTaintTrackingCfg extends TaintTracking2:: Configuration {
130- FromGlobalVarTaintTrackingCfg ( ) { this = "FromGlobalVarTaintTrackingCfg" }
124+ private module ToGlobalVarTaintTrackingFlow = TaintTracking:: Make< ToGlobalVarTaintTrackingConfig > ;
131125
132- override predicate isSource ( DataFlow:: Node source ) {
126+ private module FromGlobalVarTaintTrackingConfig implements DataFlow:: ConfigSig {
127+ predicate isSource ( DataFlow:: Node source ) {
133128 // This set of sources should be reasonably small, which is good for
134129 // performance since the set of sinks is very large.
135- exists ( ToGlobalVarTaintTrackingCfg otherCfg | otherCfg . hasFlowTo ( source ) )
130+ ToGlobalVarTaintTrackingFlow :: hasFlowTo ( source )
136131 }
137132
138- override predicate isSink ( DataFlow:: Node sink ) { exists ( adjustedSink ( sink ) ) }
133+ predicate isSink ( DataFlow:: Node sink ) { exists ( adjustedSink ( sink ) ) }
139134
140- override predicate isAdditionalTaintStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
135+ predicate isAdditionalFlowStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
141136 // Additional step for flow out of variables. There is no flow _into_
142137 // variables in this configuration, so this step only serves to take flow
143138 // out of a variable that's a source.
144139 readsVariable ( n2 .asInstruction ( ) , n1 .asVariable ( ) )
145140 }
146141
147- override predicate isSanitizer ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
142+ predicate isBarrier ( DataFlow:: Node node ) { nodeIsBarrier ( node ) }
148143
149- override predicate isSanitizerIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
144+ predicate isBarrierIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
150145}
151146
147+ private module FromGlobalVarTaintTrackingFlow =
148+ TaintTracking:: Make< FromGlobalVarTaintTrackingConfig > ;
149+
152150private predicate readsVariable ( LoadInstruction load , Variable var ) {
153151 load .getSourceAddress ( ) .( VariableAddressInstruction ) .getAstVariable ( ) = var
154152}
@@ -332,8 +330,8 @@ private import Cached
332330 */
333331cached
334332predicate 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
337335 tainted = adjustedSink ( sink )
338336 )
339337}
@@ -359,12 +357,11 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
359357 globalVar = ""
360358 or
361359 exists (
362- ToGlobalVarTaintTrackingCfg toCfg , FromGlobalVarTaintTrackingCfg fromCfg ,
363360 DataFlow:: VariableNode variableNode , GlobalOrNamespaceVariable global , DataFlow:: Node sink
364361 |
365362 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
368365 tainted = adjustedSink ( sink ) and
369366 global = globalVarFromId ( globalVar )
370367 )
@@ -422,20 +419,18 @@ module TaintedWithPath {
422419 string toString ( ) { result = "TaintTrackingConfiguration" }
423420 }
424421
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 ) {
429424 exists ( TaintTrackingConfiguration cfg , Expr e |
430425 cfg .isSource ( e ) and source = getNodeForExpr ( e )
431426 )
432427 }
433428
434- override predicate isSink ( DataFlow:: Node sink ) {
429+ predicate isSink ( DataFlow:: Node sink ) {
435430 exists ( TaintTrackingConfiguration cfg | cfg .isSink ( adjustedSink ( sink ) ) )
436431 }
437432
438- override predicate isAdditionalTaintStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
433+ predicate isAdditionalFlowStep ( DataFlow:: Node n1 , DataFlow:: Node n2 ) {
439434 conflatePointerAndPointee ( n1 , n2 )
440435 or
441436 // Steps into and out of global variables
@@ -448,13 +443,15 @@ module TaintedWithPath {
448443 additionalTaintStep ( n1 , n2 )
449444 }
450445
451- override predicate isSanitizer ( DataFlow:: Node node ) {
446+ predicate isBarrier ( DataFlow:: Node node ) {
452447 exists ( TaintTrackingConfiguration cfg , Expr e | cfg .isBarrier ( e ) and node = getNodeForExpr ( e ) )
453448 }
454449
455- override predicate isSanitizerIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
450+ predicate isBarrierIn ( DataFlow:: Node node ) { nodeIsBarrierIn ( node ) }
456451 }
457452
453+ private module AdjustedFlow = TaintTracking:: Make< AdjustedConfig > ;
454+
458455 /*
459456 * A sink `Element` may map to multiple `DataFlowX::PathNode`s via (the
460457 * inverse of) `adjustedSink`. For example, an `Expr` maps to all its
@@ -470,12 +467,12 @@ module TaintedWithPath {
470467 */
471468
472469 private newtype TPathNode =
473- TWrapPathNode ( DataFlow3 :: PathNode n ) or
470+ TWrapPathNode ( AdjustedFlow :: PathNode n ) or
474471 // There's a single newtype constructor for both sources and sinks since
475472 // that makes it easiest to deal with the case where source = sink.
476473 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 )
479476 |
480477 sourceNode = getNodeForExpr ( e ) and
481478 exists ( TaintTrackingConfiguration ttCfg | ttCfg .isSource ( e ) )
@@ -524,7 +521,7 @@ module TaintedWithPath {
524521 }
525522
526523 private class WrapPathNode extends PathNode , TWrapPathNode {
527- DataFlow3 :: PathNode inner ( ) { this = TWrapPathNode ( result ) }
524+ AdjustedFlow :: PathNode inner ( ) { this = TWrapPathNode ( result ) }
528525
529526 override string toString ( ) { result = this .inner ( ) .toString ( ) }
530527
@@ -561,25 +558,25 @@ module TaintedWithPath {
561558
562559 /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
563560 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 ( ) )
565562 or
566563 // To avoid showing trivial-looking steps, we _replace_ the last node instead
567564 // of adding an edge out of it.
568565 exists ( WrapPathNode sinkNode |
569- DataFlow3 :: PathGraph:: edges ( a .( WrapPathNode ) .inner ( ) , sinkNode .inner ( ) ) and
566+ AdjustedFlow :: PathGraph:: edges ( a .( WrapPathNode ) .inner ( ) , sinkNode .inner ( ) ) and
570567 b .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
571568 )
572569 or
573570 // Same for the first node
574571 exists ( WrapPathNode sourceNode |
575- DataFlow3 :: PathGraph:: edges ( sourceNode .inner ( ) , b .( WrapPathNode ) .inner ( ) ) and
572+ AdjustedFlow :: PathGraph:: edges ( sourceNode .inner ( ) , b .( WrapPathNode ) .inner ( ) ) and
576573 sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( a .( InitialPathNode ) .inner ( ) )
577574 )
578575 or
579576 // Finally, handle the case where the path goes directly from a source to a
580577 // sink, meaning that they both need to be translated.
581578 exists ( WrapPathNode sinkNode , WrapPathNode sourceNode |
582- DataFlow3 :: PathGraph:: edges ( sourceNode .inner ( ) , sinkNode .inner ( ) ) and
579+ AdjustedFlow :: PathGraph:: edges ( sourceNode .inner ( ) , sinkNode .inner ( ) ) and
583580 sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( a .( InitialPathNode ) .inner ( ) ) and
584581 b .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
585582 )
@@ -590,28 +587,28 @@ module TaintedWithPath {
590587 * from `par` to `ret` within it, in the graph of data flow path explanations.
591588 */
592589 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 ( ) ,
594591 ret .( WrapPathNode ) .inner ( ) , out .( WrapPathNode ) .inner ( ) )
595592 or
596593 // To avoid showing trivial-looking steps, we _replace_ the last node instead
597594 // of adding an edge out of it.
598595 exists ( WrapPathNode sinkNode |
599- DataFlow3 :: PathGraph:: subpaths ( arg .( WrapPathNode ) .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
596+ AdjustedFlow :: PathGraph:: subpaths ( arg .( WrapPathNode ) .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
600597 ret .( WrapPathNode ) .inner ( ) , sinkNode .inner ( ) ) and
601598 out .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
602599 )
603600 or
604601 // Same for the first node
605602 exists ( WrapPathNode sourceNode |
606- DataFlow3 :: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
603+ AdjustedFlow :: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
607604 ret .( WrapPathNode ) .inner ( ) , out .( WrapPathNode ) .inner ( ) ) and
608605 sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( arg .( InitialPathNode ) .inner ( ) )
609606 )
610607 or
611608 // Finally, handle the case where the path goes directly from a source to a
612609 // sink, meaning that they both need to be translated.
613610 exists ( WrapPathNode sinkNode , WrapPathNode sourceNode |
614- DataFlow3 :: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
611+ AdjustedFlow :: PathGraph:: subpaths ( sourceNode .inner ( ) , par .( WrapPathNode ) .inner ( ) ,
615612 ret .( WrapPathNode ) .inner ( ) , sinkNode .inner ( ) ) and
616613 sourceNode .inner ( ) .getNode ( ) = getNodeForExpr ( arg .( InitialPathNode ) .inner ( ) ) and
617614 out .( FinalPathNode ) .inner ( ) = adjustedSink ( sinkNode .inner ( ) .getNode ( ) )
@@ -634,10 +631,10 @@ module TaintedWithPath {
634631 * the computation.
635632 */
636633 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 |
638635 source = sourceNode .( InitialPathNode ) .inner ( ) and
639636 flowSource = getNodeForExpr ( source ) and
640- cfg . hasFlow ( flowSource , flowSink ) and
637+ AdjustedFlow :: hasFlow ( flowSource , flowSink ) and
641638 tainted = adjustedSink ( flowSink ) and
642639 tainted = sinkNode .( FinalPathNode ) .inner ( )
643640 )
@@ -660,8 +657,8 @@ module TaintedWithPath {
660657 * through a global variable.
661658 */
662659 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
665662 edgesWithoutGlobals + ( sourceNode , sinkNode ) and
666663 tainted = sinkNode .inner ( )
667664 )
0 commit comments