Skip to content

Commit d209231

Browse files
committed
C++: Remove cartesian product in 'ExecTainted'.
1 parent b944005 commit d209231

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import semmle.code.cpp.security.Security
1919
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
2020
import semmle.code.cpp.ir.IR
2121
import semmle.code.cpp.ir.dataflow.TaintTracking
22+
import semmle.code.cpp.ir.dataflow.TaintTracking2
2223
import semmle.code.cpp.security.FlowSources
2324
import semmle.code.cpp.models.implementations.Strcat
2425
import 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

88115
class 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

Comments
 (0)