@@ -6,6 +6,7 @@ import cpp
66private import semmle.code.cpp.controlflow.SSA
77private import semmle.code.cpp.dataflow.internal.SubBasicBlocks
88private import semmle.code.cpp.dataflow.internal.AddressFlow
9+ private import semmle.code.cpp.models.implementations.Iterator
910
1011/**
1112 * A conceptual variable that is assigned only once, like an SSA variable. This
@@ -109,20 +110,16 @@ class FlowVar extends TFlowVar {
109110 */
110111private module PartialDefinitions {
111112 class PartialDefinition extends Expr {
112- Expr innerDefinedExpr ;
113113 ControlFlowNode node ;
114114
115115 PartialDefinition ( ) {
116- exists ( Expr convertedInner |
117- valueToUpdate ( convertedInner , this .getFullyConverted ( ) , node ) and
118- innerDefinedExpr = convertedInner .getUnconverted ( ) and
119- not this instanceof Conversion
120- )
116+ valueToUpdate ( _, this .getFullyConverted ( ) , node ) and
117+ not this instanceof Conversion
121118 }
122119
123- deprecated predicate partiallyDefines ( Variable v ) { innerDefinedExpr = v . getAnAccess ( ) }
120+ deprecated predicate partiallyDefines ( Variable v ) { none ( ) }
124121
125- deprecated predicate partiallyDefinesThis ( ThisExpr e ) { innerDefinedExpr = e }
122+ deprecated predicate partiallyDefinesThis ( ThisExpr e ) { none ( ) }
126123
127124 /**
128125 * Gets the subBasicBlock where this `PartialDefinition` is defined.
@@ -133,10 +130,9 @@ private module PartialDefinitions {
133130 * Holds if this `PartialDefinition` defines variable `v` at control-flow
134131 * node `cfn`.
135132 */
136- pragma [ noinline]
133+ pragma [ noinline] // does this work with a dispred?
137134 predicate partiallyDefinesVariableAt ( Variable v , ControlFlowNode cfn ) {
138- innerDefinedExpr = v .getAnAccess ( ) and
139- cfn = node
135+ none ( )
140136 }
141137
142138 /**
@@ -147,10 +143,7 @@ private module PartialDefinitions {
147143 * - `inner` = `... .x`, `outer` = `&...`
148144 * - `inner` = `a`, `outer` = `*`
149145 */
150- predicate definesExpressions ( Expr inner , Expr outer ) {
151- inner = innerDefinedExpr and
152- outer = this
153- }
146+ predicate definesExpressions ( Expr inner , Expr outer ) { none ( ) }
154147
155148 /**
156149 * Gets the location of this element, adjusted to avoid unknown locations
@@ -166,6 +159,68 @@ private module PartialDefinitions {
166159 }
167160 }
168161
162+ class IteratorPartialDefinition extends PartialDefinition {
163+ Variable collection ;
164+ Call innerDefinedExpr ;
165+
166+ IteratorPartialDefinition ( ) {
167+ exists ( Expr convertedInner |
168+ valueToUpdate ( convertedInner , this .getFullyConverted ( ) , node ) and
169+ innerDefinedExpr = convertedInner .getUnconverted ( ) and
170+ innerDefinedExpr .getQualifier ( ) = getAnIteratorAccess ( collection ) and
171+ innerDefinedExpr .getTarget ( ) instanceof IteratorPointerDereferenceMemberOperator
172+ )
173+ }
174+
175+ deprecated override predicate partiallyDefines ( Variable v ) { v = collection }
176+
177+ deprecated override predicate partiallyDefinesThis ( ThisExpr e ) { none ( ) }
178+
179+ override predicate definesExpressions ( Expr inner , Expr outer ) {
180+ inner = innerDefinedExpr and
181+ outer = this
182+ }
183+
184+ override predicate partiallyDefinesVariableAt ( Variable v , ControlFlowNode cfn ) {
185+ v = collection and
186+ cfn = node
187+ }
188+ }
189+
190+ class VariablePartialDefinition extends PartialDefinition {
191+ Expr innerDefinedExpr ;
192+
193+ VariablePartialDefinition ( ) {
194+ exists ( Expr convertedInner |
195+ valueToUpdate ( convertedInner , this .getFullyConverted ( ) , node ) and
196+ innerDefinedExpr = convertedInner .getUnconverted ( ) and
197+ not this instanceof Conversion
198+ )
199+ }
200+
201+ deprecated override predicate partiallyDefines ( Variable v ) { innerDefinedExpr = v .getAnAccess ( ) }
202+
203+ deprecated override predicate partiallyDefinesThis ( ThisExpr e ) { innerDefinedExpr = e }
204+
205+ /**
206+ * Holds if this partial definition may modify `inner` (or what it points
207+ * to) through `outer`. These expressions will never be `Conversion`s.
208+ *
209+ * For example, in `f(& (*a).x)`, there are two results:
210+ * - `inner` = `... .x`, `outer` = `&...`
211+ * - `inner` = `a`, `outer` = `*`
212+ */
213+ override predicate definesExpressions ( Expr inner , Expr outer ) {
214+ inner = innerDefinedExpr and
215+ outer = this
216+ }
217+
218+ override predicate partiallyDefinesVariableAt ( Variable v , ControlFlowNode cfn ) {
219+ innerDefinedExpr = v .getAnAccess ( ) and
220+ cfn = node
221+ }
222+ }
223+
169224 /**
170225 * A partial definition that's a definition by reference.
171226 */
@@ -686,9 +741,7 @@ module FlowVar_internal {
686741 * `node instanceof Initializer` is covered by `initializer` instead of this
687742 * predicate.
688743 */
689- predicate assignmentLikeOperation (
690- ControlFlowNode node , Variable v , Expr assignedExpr
691- ) {
744+ predicate assignmentLikeOperation ( ControlFlowNode node , Variable v , Expr assignedExpr ) {
692745 // Together, the two following cases cover `Assignment`
693746 node =
694747 any ( AssignExpr ae |
@@ -715,6 +768,15 @@ module FlowVar_internal {
715768 )
716769 }
717770
771+ Expr getAnIteratorAccess ( Variable collection ) {
772+ exists ( Call c , SsaDefinition def , Variable iterator |
773+ c .getQualifier ( ) = collection .getAnAccess ( ) and
774+ c .getTarget ( ) instanceof BeginOrEndFunction and
775+ def .getAnUltimateDefiningValue ( iterator ) = c and
776+ result = def .getAUse ( iterator )
777+ )
778+ }
779+
718780 /**
719781 * Holds if `v` is initialized to have value `assignedExpr`.
720782 */
0 commit comments