@@ -19,6 +19,7 @@ import semmle.code.cpp.security.Security
1919import semmle.code.cpp.valuenumbering.GlobalValueNumbering
2020import semmle.code.cpp.ir.IR
2121import semmle.code.cpp.ir.dataflow.TaintTracking
22+ import semmle.code.cpp.ir.dataflow.TaintTracking2
2223import semmle.code.cpp.security.FlowSources
2324import semmle.code.cpp.models.implementations.Strcat
2425import DataFlow:: PathGraph
@@ -83,6 +84,32 @@ class ExecState extends DataFlow::FlowState {
8384 DataFlow:: Node getFstNode ( ) { result = fst }
8485
8586 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+ }
86113}
87114
88115class ExecTaintConfiguration extends TaintTracking:: Configuration {
@@ -94,8 +121,8 @@ class ExecTaintConfiguration extends TaintTracking::Configuration {
94121 }
95122
96123 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 )
99126 }
100127
101128 override predicate isAdditionalTaintStep (
0 commit comments