Skip to content

Commit c04e596

Browse files
authored
Merge pull request #16355 from MathiasVP/promote-iterator-to-expired-container-out-of-experimental
C++: Promote `cpp/iterator-to-expired-container` out of experimental
2 parents 797f675 + 94364f7 commit c04e596

File tree

8 files changed

+44
-11
lines changed

8 files changed

+44
-11
lines changed

cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.ql renamed to cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
* @name Iterator to expired container
33
* @description Using an iterator owned by a container whose lifetime has expired may lead to unexpected behavior.
44
* @kind problem
5-
* @precision high
5+
* @precision medium
66
* @id cpp/iterator-to-expired-container
77
* @problem.severity warning
8+
* @security-severity 8.8
89
* @tags reliability
910
* security
1011
* external/cwe/cwe-416
@@ -69,6 +70,31 @@ predicate destroyedToBeginSink(DataFlow::Node sink, FunctionCall fc) {
6970
)
7071
}
7172

73+
/**
74+
* Holds if `node1` is the node corresponding to a qualifier of a destructor
75+
* call and `node2` is a node that is destroyed as a result of `node1` being
76+
* destroyed.
77+
*/
78+
private predicate qualifierToDestroyed(DataFlow::Node node1, DataFlow::Node node2) {
79+
tempToDestructorSink(node1, _) and
80+
node2 = getADestroyedNode(node1)
81+
}
82+
83+
/**
84+
* A configuration to track flow from a destroyed node to a qualifier of
85+
* a `begin` or `end` function call.
86+
*
87+
* This configuration exists to prevent a cartesian product between all sinks and
88+
* all states in `Config::isSink`.
89+
*/
90+
module Config0 implements DataFlow::ConfigSig {
91+
predicate isSource(DataFlow::Node source) { qualifierToDestroyed(_, source) }
92+
93+
predicate isSink(DataFlow::Node sink) { destroyedToBeginSink(sink, _) }
94+
}
95+
96+
module Flow0 = DataFlow::Global<Config0>;
97+
7298
/**
7399
* A configuration to track flow from a temporary variable to the qualifier of
74100
* a destructor call, and subsequently to a qualifier of a call to `begin` or
@@ -78,12 +104,15 @@ module Config implements DataFlow::StateConfigSig {
78104
newtype FlowState =
79105
additional TempToDestructor() or
80106
additional DestroyedToBegin(DataFlow::Node n) {
81-
exists(DataFlow::Node thisOperand |
82-
tempToDestructorSink(thisOperand, _) and
83-
n = getADestroyedNode(thisOperand)
84-
)
107+
any(Flow0::PathNode pn | pn.isSource()).getNode() = n
85108
}
86109

110+
/**
111+
* Holds if `sink` is a qualifier to a call to `begin`, and `mid` is an
112+
* object that is destroyed.
113+
*/
114+
private predicate relevant(DataFlow::Node mid, DataFlow::Node sink) { Flow0::flow(mid, sink) }
115+
87116
predicate isSource(DataFlow::Node source, FlowState state) {
88117
source.asInstruction().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable and
89118
state = TempToDestructor()
@@ -92,16 +121,16 @@ module Config implements DataFlow::StateConfigSig {
92121
predicate isAdditionalFlowStep(
93122
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
94123
) {
95-
tempToDestructorSink(node1, _) and
96124
state1 = TempToDestructor() and
97125
state2 = DestroyedToBegin(node2) and
98-
node2 = getADestroyedNode(node1)
126+
qualifierToDestroyed(node1, node2)
99127
}
100128

101129
predicate isSink(DataFlow::Node sink, FlowState state) {
102-
// Note: This is a non-trivial cartesian product!
103-
// Hopefully, both of these sets are quite small in practice
104-
destroyedToBeginSink(sink, _) and state instanceof DestroyedToBegin
130+
exists(DataFlow::Node mid |
131+
relevant(mid, sink) and
132+
state = DestroyedToBegin(mid)
133+
)
105134
}
106135

107136
DataFlow::FlowFeature getAFeature() {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: newQuery
3+
---
4+
* Added a new query, `cpp/iterator-to-expired-container`, to detect the creation of iterators owned by a temporary objects that are about to be destroyed.

cpp/ql/test/experimental/query-tests/Security/CWE/CWE-416/IteratorToExpiredContainer.qlref

Lines changed: 0 additions & 1 deletion
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Security/CWE/CWE-416/IteratorToExpiredContainer.ql

0 commit comments

Comments
 (0)