@@ -123,14 +123,32 @@ class IteratorCrementNonMemberOperator extends Operator {
123123}
124124
125125private class IteratorCrementNonMemberOperatorModel extends IteratorCrementNonMemberOperator ,
126- DataFlowFunction
126+ DataFlowFunction , SideEffectFunction , AliasFunction
127127{
128128 override predicate hasDataFlow ( FunctionInput input , FunctionOutput output ) {
129129 input = getIteratorArgumentInput ( this , 0 ) and
130130 output .isReturnValue ( )
131131 or
132132 input .isParameterDeref ( 0 ) and output .isReturnValueDeref ( )
133133 }
134+
135+ override predicate hasOnlySpecificReadSideEffects ( ) { any ( ) }
136+
137+ override predicate hasOnlySpecificWriteSideEffects ( ) { any ( ) }
138+
139+ override predicate hasSpecificReadSideEffect ( ParameterIndex i , boolean buffer ) {
140+ i = 0 and buffer = false
141+ }
142+
143+ override predicate hasSpecificWriteSideEffect ( ParameterIndex i , boolean buffer , boolean mustWrite ) {
144+ // See the comment on `IteratorCrementMemberOperatorModel::hasSpecificWriteSideEffect`
145+ // for an explanation of these values.
146+ i = 0 and buffer = false and mustWrite = false
147+ }
148+
149+ override predicate parameterNeverEscapes ( int index ) { none ( ) }
150+
151+ override predicate parameterEscapesOnlyViaReturn ( int index ) { index = 0 }
134152}
135153
136154/**
@@ -146,7 +164,7 @@ class IteratorCrementMemberOperator extends MemberFunction {
146164}
147165
148166private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOperator ,
149- DataFlowFunction , TaintFunction
167+ DataFlowFunction , TaintFunction , SideEffectFunction , AliasFunction
150168{
151169 override predicate hasDataFlow ( FunctionInput input , FunctionOutput output ) {
152170 input .isQualifierAddress ( ) and
@@ -163,6 +181,28 @@ private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOp
163181 input .isQualifierObject ( ) and
164182 output .isReturnValueDeref ( )
165183 }
184+
185+ override predicate hasOnlySpecificReadSideEffects ( ) { any ( ) }
186+
187+ override predicate hasOnlySpecificWriteSideEffects ( ) { any ( ) }
188+
189+ override predicate hasSpecificReadSideEffect ( ParameterIndex i , boolean buffer ) {
190+ i = - 1 and buffer = false
191+ }
192+
193+ override predicate hasSpecificWriteSideEffect ( ParameterIndex i , boolean buffer , boolean mustWrite ) {
194+ // We have two choices here: either `buffer` must be `true` or `mustWrite`
195+ // must be `false` to ensure that the IR alias analysis doesn't think that
196+ // `it++` completely override the value of the iterator.
197+ // We choose `mustWrite` must be `false`. In that case, the value of
198+ // `buffer` isn't super important (it just decides which kind of read side
199+ // effect will be emitted).
200+ i = - 1 and buffer = false and mustWrite = false
201+ }
202+
203+ override predicate parameterNeverEscapes ( int index ) { index = - 1 }
204+
205+ override predicate parameterEscapesOnlyViaReturn ( int index ) { none ( ) }
166206}
167207
168208/**
@@ -332,7 +372,7 @@ class IteratorAssignArithmeticOperator extends Function {
332372 * non-member and member versions, use `IteratorPointerDereferenceOperator`.
333373 */
334374class IteratorPointerDereferenceMemberOperator extends MemberFunction , TaintFunction ,
335- IteratorReferenceFunction
375+ IteratorReferenceFunction , AliasFunction , SideEffectFunction
336376{
337377 IteratorPointerDereferenceMemberOperator ( ) {
338378 this .getClassAndName ( "operator*" ) instanceof Iterator
@@ -345,6 +385,18 @@ class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunc
345385 input .isReturnValueDeref ( ) and
346386 output .isQualifierObject ( )
347387 }
388+
389+ override predicate parameterNeverEscapes ( int index ) { index = - 1 }
390+
391+ override predicate parameterEscapesOnlyViaReturn ( int index ) { none ( ) }
392+
393+ override predicate hasOnlySpecificReadSideEffects ( ) { any ( ) }
394+
395+ override predicate hasOnlySpecificWriteSideEffects ( ) { any ( ) }
396+
397+ override predicate hasSpecificReadSideEffect ( ParameterIndex i , boolean buffer ) {
398+ i = - 1 and buffer = false
399+ }
348400}
349401
350402/**
@@ -361,7 +413,7 @@ class IteratorPointerDereferenceNonMemberOperator extends Operator, IteratorRefe
361413}
362414
363415private class IteratorPointerDereferenceNonMemberOperatorModel extends IteratorPointerDereferenceNonMemberOperator ,
364- TaintFunction
416+ TaintFunction , AliasFunction , SideEffectFunction
365417{
366418 override predicate hasTaintFlow ( FunctionInput input , FunctionOutput output ) {
367419 input = getIteratorArgumentInput ( this , 0 ) and
@@ -370,6 +422,18 @@ private class IteratorPointerDereferenceNonMemberOperatorModel extends IteratorP
370422 input .isReturnValueDeref ( ) and
371423 output .isParameterDeref ( 0 )
372424 }
425+
426+ override predicate parameterNeverEscapes ( int index ) { index = 0 }
427+
428+ override predicate parameterEscapesOnlyViaReturn ( int index ) { none ( ) }
429+
430+ override predicate hasOnlySpecificReadSideEffects ( ) { any ( ) }
431+
432+ override predicate hasOnlySpecificWriteSideEffects ( ) { any ( ) }
433+
434+ override predicate hasSpecificReadSideEffect ( ParameterIndex i , boolean buffer ) {
435+ i = 0 and buffer = false
436+ }
373437}
374438
375439/**
@@ -420,6 +484,71 @@ class IteratorAssignmentMemberOperator extends MemberFunction {
420484 }
421485}
422486
487+ /**
488+ * A member `operator==` or `operator!=` function for an iterator type.
489+ *
490+ * Note that this class _only_ matches member functions. To find both
491+ * non-member and member versions, use `IteratorLogicalOperator`.
492+ */
493+ class IteratorLogicalMemberOperator extends MemberFunction {
494+ IteratorLogicalMemberOperator ( ) {
495+ this .getClassAndName ( [ "operator!=" , "operator==" ] ) instanceof Iterator
496+ }
497+ }
498+
499+ private class IteratorLogicalMemberOperatorModel extends IteratorLogicalMemberOperator ,
500+ AliasFunction , SideEffectFunction
501+ {
502+ override predicate parameterNeverEscapes ( int index ) { index = [ - 1 , 0 ] }
503+
504+ override predicate parameterEscapesOnlyViaReturn ( int index ) { none ( ) }
505+
506+ override predicate hasOnlySpecificReadSideEffects ( ) { any ( ) }
507+
508+ override predicate hasOnlySpecificWriteSideEffects ( ) { any ( ) }
509+
510+ override predicate hasSpecificReadSideEffect ( ParameterIndex i , boolean buffer ) {
511+ i = - 1 and buffer = false
512+ }
513+ }
514+
515+ /**
516+ * A member `operator==` or `operator!=` function for an iterator type.
517+ *
518+ * Note that this class _only_ matches non-member functions. To find both
519+ * non-member and member versions, use `IteratorLogicalOperator`.
520+ */
521+ class IteratorLogicalNonMemberOperator extends Function {
522+ IteratorLogicalNonMemberOperator ( ) {
523+ this .hasName ( [ "operator!=" , "operator==" ] ) and
524+ exists ( getIteratorArgumentInput ( this , 0 ) ) and
525+ exists ( getIteratorArgumentInput ( this , 1 ) )
526+ }
527+ }
528+
529+ private class IteratorLogicalNonMemberOperatorModel extends IteratorLogicalNonMemberOperator ,
530+ AliasFunction , SideEffectFunction
531+ {
532+ override predicate parameterNeverEscapes ( int index ) { index = [ 0 , 1 ] }
533+
534+ override predicate parameterEscapesOnlyViaReturn ( int index ) { none ( ) }
535+
536+ override predicate hasOnlySpecificReadSideEffects ( ) { any ( ) }
537+
538+ override predicate hasOnlySpecificWriteSideEffects ( ) { any ( ) }
539+ }
540+
541+ /**
542+ * A (member or non-member) `operator==` or `operator!=` function for an iterator type.
543+ */
544+ class IteratorLogicalOperator extends Function {
545+ IteratorLogicalOperator ( ) {
546+ this instanceof IteratorLogicalNonMemberOperator
547+ or
548+ this instanceof IteratorLogicalMemberOperator
549+ }
550+ }
551+
423552/**
424553 * An `operator=` member function of an iterator class that is not a copy or move assignment
425554 * operator.
@@ -428,12 +557,26 @@ class IteratorAssignmentMemberOperator extends MemberFunction {
428557 * `operator*` and use their own `operator=` to assign to the container.
429558 */
430559private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMemberOperator ,
431- TaintFunction
560+ TaintFunction , SideEffectFunction , AliasFunction
432561{
433562 override predicate hasTaintFlow ( FunctionInput input , FunctionOutput output ) {
434563 input .isParameterDeref ( 0 ) and
435564 output .isQualifierObject ( )
436565 }
566+
567+ override predicate hasOnlySpecificReadSideEffects ( ) { any ( ) }
568+
569+ override predicate hasOnlySpecificWriteSideEffects ( ) { any ( ) }
570+
571+ override predicate hasSpecificWriteSideEffect ( ParameterIndex i , boolean buffer , boolean mustWrite ) {
572+ // See the comment on `IteratorCrementMemberOperatorModel::hasSpecificWriteSideEffect`
573+ // for an explanation of these values.
574+ i = - 1 and buffer = false and mustWrite = false
575+ }
576+
577+ override predicate parameterNeverEscapes ( int index ) { index = 0 }
578+
579+ override predicate parameterEscapesOnlyViaReturn ( int index ) { index = - 1 }
437580}
438581
439582/**
0 commit comments