@@ -22,7 +22,7 @@ import semmle.code.cpp.ir.dataflow.TaintTracking
22
22
import semmle.code.cpp.ir.dataflow.TaintTracking2
23
23
import semmle.code.cpp.security.FlowSources
24
24
import semmle.code.cpp.models.implementations.Strcat
25
- import DataFlow :: PathGraph
25
+ import ExecTaint :: PathGraph
26
26
27
27
Expr sinkAsArgumentIndirection ( DataFlow:: Node sink ) {
28
28
result =
@@ -67,74 +67,71 @@ predicate interestingConcatenation(DataFlow::Node fst, DataFlow::Node snd) {
67
67
)
68
68
}
69
69
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" }
72
76
}
73
77
74
- class ExecState extends DataFlow :: FlowState {
78
+ class ExecState extends TExecState {
75
79
DataFlow:: Node fst ;
76
80
DataFlow:: Node snd ;
77
81
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 ) }
83
83
84
84
DataFlow:: Node getFstNode ( ) { result = fst }
85
85
86
86
DataFlow:: Node getSndNode ( ) { result = snd }
87
87
88
88
/** 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" }
92
92
}
93
93
94
94
/**
95
95
* A `TaintTracking` configuration that's used to find the relevant `ExecState`s for a
96
96
* given sink. This avoids a cartesian product between all sinks and all `ExecState`s in
97
97
* `ExecTaintConfiguration::isSink`.
98
98
*/
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 ) {
103
101
exists ( ExecState state | state .getSndNode ( ) = source )
104
102
}
105
103
106
- override predicate isSink ( DataFlow:: Node sink ) {
107
- shellCommand ( sinkAsArgumentIndirection ( sink ) , _)
108
- }
104
+ predicate isSink ( DataFlow:: Node sink ) { shellCommand ( sinkAsArgumentIndirection ( sink ) , _) }
109
105
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
112
108
}
113
109
}
114
110
115
- class ExecTaintConfiguration extends TaintTracking:: Configuration {
116
- ExecTaintConfiguration ( ) { this = "ExecTaintConfiguration" }
111
+ module ExecState = TaintTracking:: Make< ExecStateConfiguration > ;
117
112
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 ) {
119
117
source instanceof FlowSource and
120
118
state instanceof ConcatState
121
119
}
122
120
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
125
123
state .( ExecState ) .isFeasibleForSink ( sink )
126
124
}
127
125
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
131
128
) {
132
129
state1 instanceof ConcatState and
133
130
state2 .( ExecState ) .getFstNode ( ) = node1 and
134
131
state2 .( ExecState ) .getSndNode ( ) = node2
135
132
}
136
133
137
- override predicate isSanitizer ( DataFlow:: Node node , DataFlow :: FlowState state ) {
134
+ predicate isBarrier ( DataFlow:: Node node , FlowState state ) {
138
135
(
139
136
node .asInstruction ( ) .getResultType ( ) instanceof IntegralType
140
137
or
@@ -143,16 +140,18 @@ class ExecTaintConfiguration extends TaintTracking::Configuration {
143
140
state instanceof ConcatState
144
141
}
145
142
146
- override predicate isSanitizerOut ( DataFlow:: Node node ) {
143
+ predicate isBarrierOut ( DataFlow:: Node node ) {
147
144
isSink ( node , _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
148
145
}
149
146
}
150
147
148
+ module ExecTaint = TaintTracking:: MakeWithState< ExecTaintConfiguration > ;
149
+
151
150
from
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
154
153
where
155
- conf . hasFlowPath ( sourceNode , sinkNode ) and
154
+ ExecTaint :: hasFlowPath ( sourceNode , sinkNode ) and
156
155
taintCause = sourceNode .getNode ( ) .( FlowSource ) .getSourceType ( ) and
157
156
shellCommand ( sinkAsArgumentIndirection ( sinkNode .getNode ( ) ) , callChain ) and
158
157
concatResult = sinkNode .getState ( ) .( ExecState ) .getSndNode ( )
0 commit comments