@@ -19,6 +19,7 @@ import semmle.code.cpp.security.Security
19
19
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
20
20
import semmle.code.cpp.ir.IR
21
21
import semmle.code.cpp.ir.dataflow.TaintTracking
22
+ import semmle.code.cpp.ir.dataflow.TaintTracking2
22
23
import semmle.code.cpp.security.FlowSources
23
24
import semmle.code.cpp.models.implementations.Strcat
24
25
import DataFlow:: PathGraph
@@ -83,6 +84,32 @@ class ExecState extends DataFlow::FlowState {
83
84
DataFlow:: Node getFstNode ( ) { result = fst }
84
85
85
86
DataFlow:: Node getSndNode ( ) { result = snd }
87
+
88
+ /** Holds if this is a possible `ExecState` for `sink`. */
89
+ predicate isFeasibleForSink ( DataFlow:: Node sink ) {
90
+ any ( ExecStateConfiguration conf ) .hasFlow ( snd , sink )
91
+ }
92
+ }
93
+
94
+ /**
95
+ * A `TaintTracking` configuration that's used to find the relevant `ExecState`s for a
96
+ * given sink. This avoids a cartesian product between all sinks and all `ExecState`s in
97
+ * `ExecTaintConfiguration::isSink`.
98
+ */
99
+ class ExecStateConfiguration extends TaintTracking2:: Configuration {
100
+ ExecStateConfiguration ( ) { this = "ExecStateConfiguration" }
101
+
102
+ override predicate isSource ( DataFlow:: Node source ) {
103
+ exists ( ExecState state | state .getSndNode ( ) = source )
104
+ }
105
+
106
+ override predicate isSink ( DataFlow:: Node sink ) {
107
+ shellCommand ( sinkAsArgumentIndirection ( sink ) , _)
108
+ }
109
+
110
+ override predicate isSanitizerOut ( DataFlow:: Node node ) {
111
+ isSink ( node , _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
112
+ }
86
113
}
87
114
88
115
class ExecTaintConfiguration extends TaintTracking:: Configuration {
@@ -94,8 +121,8 @@ class ExecTaintConfiguration extends TaintTracking::Configuration {
94
121
}
95
122
96
123
override predicate isSink ( DataFlow:: Node sink , DataFlow:: FlowState state ) {
97
- shellCommand ( sinkAsArgumentIndirection ( sink ) , _ ) and
98
- state instanceof ExecState
124
+ any ( ExecStateConfiguration conf ) . isSink ( sink ) and
125
+ state . ( ExecState ) . isFeasibleForSink ( sink )
99
126
}
100
127
101
128
override predicate isAdditionalTaintStep (
0 commit comments