@@ -188,6 +188,93 @@ private class PointerOrReferenceTypeIndirection extends Indirection instanceof P
188188 override predicate isAdditionalWrite ( Node0Impl value , Operand address , boolean certain ) { none ( ) }
189189}
190190
191+ private module IteratorIndirections {
192+ import semmle.code.cpp.models.interfaces.Iterator as Interfaces
193+ import semmle.code.cpp.models.implementations.Iterator as Iterator
194+ import semmle.code.cpp.models.implementations.StdContainer as StdContainer
195+
196+ class IteratorIndirection extends Indirection instanceof Interfaces:: Iterator {
197+ IteratorIndirection ( ) {
198+ not this instanceof PointerOrReferenceTypeIndirection and baseType = super .getValueType ( )
199+ }
200+
201+ override int getNumberOfIndirections ( ) { result = 1 + countIndirections ( this .getBaseType ( ) ) }
202+
203+ override predicate isAdditionalDereference ( Instruction deref , Operand address ) {
204+ exists ( CallInstruction call |
205+ operandForfullyConvertedCall ( deref .getAUse ( ) , call ) and
206+ this = call .getStaticCallTarget ( ) .getClassAndName ( "operator*" ) and
207+ address = call .getThisArgumentOperand ( )
208+ )
209+ }
210+
211+ override predicate isAdditionalWrite ( Node0Impl value , Operand address , boolean certain ) {
212+ exists ( CallInstruction call | call .getArgumentOperand ( 0 ) = value .asOperand ( ) |
213+ this = call .getStaticCallTarget ( ) .getClassAndName ( "operator=" ) and
214+ address = call .getThisArgumentOperand ( ) and
215+ certain = false
216+ )
217+ }
218+
219+ override predicate isAdditionalTaintStep ( Node node1 , Node node2 ) {
220+ exists ( CallInstruction call |
221+ // Taint through `operator+=` and `operator-=` on iterators.
222+ call .getStaticCallTarget ( ) instanceof Iterator:: IteratorAssignArithmeticOperator and
223+ node2 .( IndirectArgumentOutNode ) .getPreUpdateNode ( ) = node1 and
224+ node1 .( IndirectOperand ) .getOperand ( ) = call .getArgumentOperand ( 0 ) and
225+ node1 .getType ( ) .getUnspecifiedType ( ) = this
226+ )
227+ }
228+
229+ override predicate isAdditionalConversionFlow ( Operand opFrom , Instruction instrTo ) {
230+ // This is a bit annoying: Consider the following snippet:
231+ // ```
232+ // struct MyIterator {
233+ // ...
234+ // insert_iterator_by_trait operator*();
235+ // insert_iterator_by_trait operator=(int x);
236+ // };
237+ // ...
238+ // MyIterator it;
239+ // ...
240+ // *it = source();
241+ // ```
242+ // The qualifier to `operator*` will undergo prvalue-to-xvalue conversion and a
243+ // temporary object will be created. Thus, the IR for the call to `operator=` will
244+ // look like (simplified):
245+ // ```
246+ // r1(glval<MyIterator>) = VariableAddress[it] :
247+ // r2(glval<unknown>) = FunctionAddress[operator*] :
248+ // r3(MyIterator) = Call[operator*] : func:r2, this:r1
249+ // r4(glval<MyIterator>) = VariableAddress[#temp] :
250+ // m1(MyIterator) = Store[#temp] : &:r4, r3
251+ // r5(glval<unknown>) = FunctionAddress[operator=] :
252+ // r6(glval<unknown>) = FunctionAddress[source] :
253+ // r7(int) = Call[source] : func:r6
254+ // r8(MyIterator) = Call[operator=] : func:r5, this:r4, 0:r7
255+ // ```
256+ // in order to properly recognize that the qualifier to the call to `operator=` accesses
257+ // `it` we look for the store that writes to the temporary object, and use the source value
258+ // of that store as the "address" to continue searching for the base variable `it`.
259+ exists ( StoreInstruction store , VariableInstruction var |
260+ var = instrTo and
261+ var .getIRVariable ( ) instanceof IRTempVariable and
262+ opFrom .getType ( ) = this and
263+ store .getSourceValueOperand ( ) = opFrom and
264+ store .getDestinationAddress ( ) = var
265+ )
266+ or
267+ // A call to `operator++` or `operator--` is the iterator equivalent version of a
268+ // pointer arithmetic instruction.
269+ exists ( CallInstruction call |
270+ instrTo = call and
271+ call .getStaticCallTarget ( ) instanceof Iterator:: IteratorCrementMemberOperator and
272+ opFrom = call .getThisArgumentOperand ( )
273+ )
274+ }
275+ }
276+ }
277+
191278predicate isDereference ( Instruction deref , Operand address ) {
192279 any ( Indirection ind ) .isAdditionalDereference ( deref , address )
193280 or
0 commit comments