@@ -22,7 +22,7 @@ import semmle.code.cpp.ir.dataflow.TaintTracking
2222import semmle.code.cpp.ir.dataflow.TaintTracking2
2323import semmle.code.cpp.security.FlowSources
2424import semmle.code.cpp.models.implementations.Strcat
25- import DataFlow :: PathGraph
25+ import ExecTaint :: PathGraph
2626
2727Expr sinkAsArgumentIndirection ( DataFlow:: Node sink ) {
2828 result =
@@ -67,74 +67,71 @@ predicate interestingConcatenation(DataFlow::Node fst, DataFlow::Node snd) {
6767 )
6868}
6969
70- class ConcatState extends DataFlow:: FlowState {
71- ConcatState ( ) { this = "ConcatState" }
70+ newtype TState =
71+ TConcatState ( ) or
72+ TExecState ( DataFlow:: Node fst , DataFlow:: Node snd ) { interestingConcatenation ( fst , snd ) }
73+
74+ class ConcatState extends TConcatState {
75+ string toString ( ) { result = "ConcatState" }
7276}
7377
74- class ExecState extends DataFlow :: FlowState {
78+ class ExecState extends TExecState {
7579 DataFlow:: Node fst ;
7680 DataFlow:: Node snd ;
7781
78- ExecState ( ) {
79- this =
80- "ExecState (" + fst .getLocation ( ) + " | " + fst + ", " + snd .getLocation ( ) + " | " + snd + ")" and
81- interestingConcatenation ( pragma [ only_bind_into ] ( fst ) , pragma [ only_bind_into ] ( snd ) )
82- }
82+ ExecState ( ) { this = TExecState ( fst , snd ) }
8383
8484 DataFlow:: Node getFstNode ( ) { result = fst }
8585
8686 DataFlow:: Node getSndNode ( ) { result = snd }
8787
8888 /** Holds if this is a possible `ExecState` for `sink`. */
89- predicate isFeasibleForSink ( DataFlow:: Node sink ) {
90- any ( ExecStateConfiguration conf ) . hasFlow ( snd , sink )
91- }
89+ predicate isFeasibleForSink ( DataFlow:: Node sink ) { ExecState :: hasFlow ( snd , sink ) }
90+
91+ string toString ( ) { result = "ExecState" }
9292}
9393
9494/**
9595 * A `TaintTracking` configuration that's used to find the relevant `ExecState`s for a
9696 * given sink. This avoids a cartesian product between all sinks and all `ExecState`s in
9797 * `ExecTaintConfiguration::isSink`.
9898 */
99- class ExecStateConfiguration extends TaintTracking2:: Configuration {
100- ExecStateConfiguration ( ) { this = "ExecStateConfiguration" }
101-
102- override predicate isSource ( DataFlow:: Node source ) {
99+ module ExecStateConfiguration implements DataFlow:: ConfigSig {
100+ predicate isSource ( DataFlow:: Node source ) {
103101 exists ( ExecState state | state .getSndNode ( ) = source )
104102 }
105103
106- override predicate isSink ( DataFlow:: Node sink ) {
107- shellCommand ( sinkAsArgumentIndirection ( sink ) , _)
108- }
104+ predicate isSink ( DataFlow:: Node sink ) { shellCommand ( sinkAsArgumentIndirection ( sink ) , _) }
109105
110- override predicate isSanitizerOut ( DataFlow:: Node node ) {
111- isSink ( node , _ ) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
106+ predicate isBarrierOut ( DataFlow:: Node node ) {
107+ isSink ( node ) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
112108 }
113109}
114110
115- class ExecTaintConfiguration extends TaintTracking:: Configuration {
116- ExecTaintConfiguration ( ) { this = "ExecTaintConfiguration" }
111+ module ExecState = TaintTracking:: Make< ExecStateConfiguration > ;
117112
118- override predicate isSource ( DataFlow:: Node source , DataFlow:: FlowState state ) {
113+ module ExecTaintConfiguration implements DataFlow:: StateConfigSig {
114+ class FlowState = TState ;
115+
116+ predicate isSource ( DataFlow:: Node source , FlowState state ) {
119117 source instanceof FlowSource and
120118 state instanceof ConcatState
121119 }
122120
123- override predicate isSink ( DataFlow:: Node sink , DataFlow :: FlowState state ) {
124- any ( ExecStateConfiguration conf ) . isSink ( sink ) and
121+ predicate isSink ( DataFlow:: Node sink , FlowState state ) {
122+ ExecStateConfiguration:: isSink ( sink ) and
125123 state .( ExecState ) .isFeasibleForSink ( sink )
126124 }
127125
128- override predicate isAdditionalTaintStep (
129- DataFlow:: Node node1 , DataFlow:: FlowState state1 , DataFlow:: Node node2 ,
130- DataFlow:: FlowState state2
126+ predicate isAdditionalFlowStep (
127+ DataFlow:: Node node1 , FlowState state1 , DataFlow:: Node node2 , FlowState state2
131128 ) {
132129 state1 instanceof ConcatState and
133130 state2 .( ExecState ) .getFstNode ( ) = node1 and
134131 state2 .( ExecState ) .getSndNode ( ) = node2
135132 }
136133
137- override predicate isSanitizer ( DataFlow:: Node node , DataFlow :: FlowState state ) {
134+ predicate isBarrier ( DataFlow:: Node node , FlowState state ) {
138135 (
139136 node .asInstruction ( ) .getResultType ( ) instanceof IntegralType
140137 or
@@ -143,16 +140,18 @@ class ExecTaintConfiguration extends TaintTracking::Configuration {
143140 state instanceof ConcatState
144141 }
145142
146- override predicate isSanitizerOut ( DataFlow:: Node node ) {
143+ predicate isBarrierOut ( DataFlow:: Node node ) {
147144 isSink ( node , _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
148145 }
149146}
150147
148+ module ExecTaint = TaintTracking:: MakeWithState< ExecTaintConfiguration > ;
149+
151150from
152- ExecTaintConfiguration conf , DataFlow :: PathNode sourceNode , DataFlow :: PathNode sinkNode ,
153- string taintCause , string callChain , DataFlow:: Node concatResult
151+ ExecTaint :: PathNode sourceNode , ExecTaint :: PathNode sinkNode , string taintCause , string callChain ,
152+ DataFlow:: Node concatResult
154153where
155- conf . hasFlowPath ( sourceNode , sinkNode ) and
154+ ExecTaint :: hasFlowPath ( sourceNode , sinkNode ) and
156155 taintCause = sourceNode .getNode ( ) .( FlowSource ) .getSourceType ( ) and
157156 shellCommand ( sinkAsArgumentIndirection ( sinkNode .getNode ( ) ) , callChain ) and
158157 concatResult = sinkNode .getState ( ) .( ExecState ) .getSndNode ( )
0 commit comments