@@ -246,14 +246,6 @@ private module IteratorIndirections {
246246 baseType = super .getValueType ( )
247247 }
248248
249- override predicate isAdditionalDereference ( Instruction deref , Operand address ) {
250- exists ( CallInstruction call |
251- operandForFullyConvertedCall ( getAUse ( deref ) , call ) and
252- this = call .getStaticCallTarget ( ) .getClassAndName ( "operator*" ) and
253- address = call .getThisArgumentOperand ( )
254- )
255- }
256-
257249 override predicate isAdditionalWrite ( Node0Impl value , Operand address , boolean certain ) {
258250 exists ( CallInstruction call | call .getArgumentOperand ( 0 ) = value .asOperand ( ) |
259251 this = call .getStaticCallTarget ( ) .getClassAndName ( "operator=" ) and
@@ -262,16 +254,6 @@ private module IteratorIndirections {
262254 )
263255 }
264256
265- override predicate isAdditionalTaintStep ( Node node1 , Node node2 ) {
266- exists ( CallInstruction call |
267- // Taint through `operator+=` and `operator-=` on iterators.
268- call .getStaticCallTarget ( ) instanceof Iterator:: IteratorAssignArithmeticOperator and
269- node2 .( IndirectArgumentOutNode ) .getPreUpdateNode ( ) = node1 and
270- node1 .( IndirectOperand ) .hasOperandAndIndirectionIndex ( call .getArgumentOperand ( 0 ) , _) and
271- node1 .getType ( ) .getUnspecifiedType ( ) = this
272- )
273- }
274-
275257 override predicate isAdditionalConversionFlow ( Operand opFrom , Instruction instrTo ) {
276258 // This is a bit annoying: Consider the following snippet:
277259 // ```
@@ -589,230 +571,6 @@ private class BaseCallInstruction extends BaseSourceVariableInstruction, CallIns
589571
590572cached
591573private module Cached {
592- private import semmle.code.cpp.models.interfaces.Iterator as Interfaces
593- private import semmle.code.cpp.models.implementations.Iterator as Iterator
594- private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as IO
595-
596- /**
597- * Holds if `next` is a instruction with a memory result that potentially
598- * updates the memory produced by `prev`.
599- */
600- private predicate memorySucc ( Instruction prev , Instruction next ) {
601- prev = next .( ChiInstruction ) .getTotal ( )
602- or
603- // Phi inputs can be inexact.
604- prev = next .( PhiInstruction ) .getAnInputOperand ( ) .getAnyDef ( )
605- or
606- prev = next .( CopyInstruction ) .getSourceValue ( )
607- or
608- exists ( ReadSideEffectInstruction read |
609- next = read .getPrimaryInstruction ( ) and
610- isAdditionalConversionFlow ( _, next ) and
611- prev = read .getSideEffectOperand ( ) .getAnyDef ( )
612- )
613- }
614-
615- /**
616- * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
617- * that is used for a write operation that writes the value `value`. The `memory` instruction
618- * represents the memory that the IR's SSA analysis determined was read by the call to `operator*`.
619- *
620- * The `numberOfLoads` integer represents the number of dereferences this write corresponds to
621- * on the underlying container that produced the iterator.
622- */
623- private predicate isChiAfterIteratorDef (
624- Instruction memory , Operand iteratorDerefAddress , Node0Impl value , int numberOfLoads
625- ) {
626- exists (
627- BaseSourceVariableInstruction iteratorBase , ReadSideEffectInstruction read ,
628- Operand iteratorAddress
629- |
630- numberOfLoads >= 0 and
631- isDef ( _, value , iteratorDerefAddress , iteratorBase , numberOfLoads + 2 , 0 ) and
632- isUse ( _, iteratorAddress , iteratorBase , numberOfLoads + 1 , 0 ) and
633- iteratorBase .getResultType ( ) instanceof Interfaces:: Iterator and
634- isDereference ( iteratorAddress .getDef ( ) , read .getArgumentDef ( ) .getAUse ( ) , _) and
635- memory = read .getSideEffectOperand ( ) .getAnyDef ( )
636- )
637- }
638-
639- private predicate isSource ( Instruction instr , Operand iteratorAddress , int numberOfLoads ) {
640- getAUse ( instr ) = iteratorAddress and
641- exists ( BaseSourceVariableInstruction iteratorBase |
642- iteratorBase .getResultType ( ) instanceof Interfaces:: Iterator and
643- not iteratorBase .getResultType ( ) instanceof Cpp:: PointerType and
644- isUse ( _, iteratorAddress , iteratorBase , numberOfLoads - 1 , 0 )
645- )
646- }
647-
648- private predicate isSink ( Instruction instr , CallInstruction call ) {
649- getAUse ( instr ) .( ArgumentOperand ) .getCall ( ) = call and
650- // Only include operations that may modify the object that the iterator points to.
651- // The following is a non-exhaustive list of things that may modify the value of the
652- // iterator, but never the value of what the iterator points to.
653- // The more things we can exclude here, the faster the small dataflow-like analysis
654- // done by `convertsIntoArgument` will converge.
655- not exists ( Function f | f = call .getStaticCallTarget ( ) |
656- f instanceof Iterator:: IteratorCrementOperator or
657- f instanceof Iterator:: IteratorBinaryArithmeticOperator or
658- f instanceof Iterator:: IteratorAssignArithmeticOperator or
659- f instanceof Iterator:: IteratorCrementMemberOperator or
660- f instanceof Iterator:: IteratorBinaryArithmeticMemberOperator or
661- f instanceof Iterator:: IteratorAssignArithmeticMemberOperator or
662- f instanceof Iterator:: IteratorAssignmentMemberOperator
663- )
664- }
665-
666- private predicate convertsIntoArgumentFwd ( Instruction instr ) {
667- isSource ( instr , _, _)
668- or
669- exists ( Instruction prev | convertsIntoArgumentFwd ( prev ) |
670- conversionFlow ( unique( | | getAUse ( prev ) ) , instr , false , _)
671- )
672- }
673-
674- private predicate convertsIntoArgumentRev ( Instruction instr ) {
675- convertsIntoArgumentFwd ( instr ) and
676- (
677- isSink ( instr , _)
678- or
679- exists ( Instruction next | convertsIntoArgumentRev ( next ) |
680- conversionFlow ( unique( | | getAUse ( instr ) ) , next , false , _)
681- )
682- )
683- }
684-
685- private predicate convertsIntoArgument (
686- Operand iteratorAddress , CallInstruction call , int numberOfLoads
687- ) {
688- exists ( Instruction iteratorAddressDef |
689- isSource ( iteratorAddressDef , iteratorAddress , numberOfLoads ) and
690- isSink ( iteratorAddressDef , call ) and
691- convertsIntoArgumentRev ( pragma [ only_bind_into ] ( iteratorAddressDef ) )
692- )
693- }
694-
695- private predicate isChiAfterIteratorArgument (
696- Instruction memory , Operand iteratorAddress , int numberOfLoads
697- ) {
698- // Ideally, `iteratorAddress` would be an `ArgumentOperand`, but there might be
699- // various conversions applied to it before it becomes an argument.
700- // So we do a small amount of flow to find the call that the iterator is passed to.
701- exists ( CallInstruction call | convertsIntoArgument ( iteratorAddress , call , numberOfLoads ) |
702- exists ( ReadSideEffectInstruction read |
703- read .getPrimaryInstruction ( ) = call and
704- read .getSideEffectOperand ( ) .getAnyDef ( ) = memory
705- )
706- or
707- exists ( LoadInstruction load |
708- iteratorAddress .getDef ( ) = load and
709- memory = load .getSourceValueOperand ( ) .getAnyDef ( )
710- )
711- )
712- }
713-
714- /**
715- * Holds if `iterator` is a `StoreInstruction` that stores the result of some function
716- * returning an iterator into an address computed started at `containerBase`.
717- *
718- * For example, given a declaration like `std::vector<int>::iterator it = v.begin()`,
719- * the `iterator` will be the `StoreInstruction` generated by the write to `it`, and
720- * `containerBase` will be the address of `v`.
721- */
722- private predicate isChiAfterBegin (
723- BaseSourceVariableInstruction containerBase , StoreInstruction iterator
724- ) {
725- exists (
726- CallInstruction getIterator , Iterator:: GetIteratorFunction getIteratorFunction ,
727- IO:: FunctionInput input , int i
728- |
729- getIterator = iterator .getSourceValue ( ) and
730- getIteratorFunction = getIterator .getStaticCallTarget ( ) and
731- getIteratorFunction .getsIterator ( input , _) and
732- isDef ( _, any ( Node0Impl n | n .asInstruction ( ) = iterator ) , _, _, 1 , 0 ) and
733- input .isParameterDerefOrQualifierObject ( i ) and
734- isUse ( _, getIterator .getArgumentOperand ( i ) , containerBase , 0 , 0 )
735- )
736- }
737-
738- /**
739- * Holds if `iteratorAddress` is an address of an iterator that is used for
740- * a read operation. The `memory` instruction represents the memory that
741- * the IR's SSA analysis determined was read by the call to `operator*`.
742- *
743- * Finally, the `numberOfLoads` integer represents the number of dereferences
744- * this read corresponds to on the underlying container that produced the iterator.
745- */
746- private predicate isChiBeforeIteratorUse (
747- Operand iteratorAddress , Instruction memory , int numberOfLoads
748- ) {
749- exists (
750- BaseSourceVariableInstruction iteratorBase , LoadInstruction load ,
751- ReadSideEffectInstruction read , Operand iteratorDerefAddress
752- |
753- numberOfLoads >= 0 and
754- isUse ( _, iteratorAddress , iteratorBase , numberOfLoads + 1 , 0 ) and
755- isUse ( _, iteratorDerefAddress , iteratorBase , numberOfLoads + 2 , 0 ) and
756- iteratorBase .getResultType ( ) instanceof Interfaces:: Iterator and
757- load .getSourceAddressOperand ( ) = iteratorDerefAddress and
758- read .getPrimaryInstruction ( ) = load .getSourceAddress ( ) and
759- memory = read .getSideEffectOperand ( ) .getAnyDef ( )
760- )
761- }
762-
763- /**
764- * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
765- * that is used for a write operation that writes the value `value` to a container that
766- * created the iterator. `container` represents the base of the address of the container
767- * that was used to create the iterator.
768- */
769- cached
770- predicate isIteratorDef (
771- BaseSourceVariableInstruction container , Operand iteratorDerefAddress , Node0Impl value ,
772- int numberOfLoads , int indirectionIndex
773- ) {
774- exists ( Instruction memory , Instruction begin , int upper , int ind |
775- isChiAfterIteratorDef ( memory , iteratorDerefAddress , value , numberOfLoads ) and
776- memorySucc * ( begin , memory ) and
777- isChiAfterBegin ( container , begin ) and
778- upper = countIndirectionsForCppType ( getResultLanguageType ( container ) ) and
779- ind = numberOfLoads + [ 1 .. upper ] and
780- indirectionIndex = ind - ( numberOfLoads + 1 )
781- )
782- }
783-
784- /**
785- * Holds if `iteratorAddress` is an address of an iterator that is used for a
786- * read operation to read a value from a container that created the iterator.
787- * `container` represents the base of the address of the container that was used
788- * to create the iterator.
789- */
790- cached
791- predicate isIteratorUse (
792- BaseSourceVariableInstruction container , Operand iteratorAddress , int numberOfLoads ,
793- int indirectionIndex
794- ) {
795- // Direct use
796- exists ( Instruction begin , Instruction memory , int upper , int ind |
797- isChiBeforeIteratorUse ( iteratorAddress , memory , numberOfLoads ) and
798- memorySucc * ( begin , memory ) and
799- isChiAfterBegin ( container , begin ) and
800- upper = countIndirectionsForCppType ( getResultLanguageType ( container ) ) and
801- ind = numberOfLoads + [ 1 .. upper ] and
802- indirectionIndex = ind - ( numberOfLoads + 1 )
803- )
804- or
805- // Use through function output
806- exists ( Instruction memory , Instruction begin , int upper , int ind |
807- isChiAfterIteratorArgument ( memory , iteratorAddress , numberOfLoads ) and
808- memorySucc * ( begin , memory ) and
809- isChiAfterBegin ( container , begin ) and
810- upper = countIndirectionsForCppType ( getResultLanguageType ( container ) ) and
811- ind = numberOfLoads + [ 1 .. upper ] and
812- indirectionIndex = ind - ( numberOfLoads - 1 )
813- )
814- }
815-
816574 /** Holds if `op` is the only use of its defining instruction, and that op is used in a conversation */
817575 private predicate isConversion ( Operand op ) {
818576 exists ( Instruction def , Operand use |
0 commit comments