@@ -15,23 +15,44 @@ import cpp
15
15
import codingstandards.cpp.cert
16
16
import codingstandards.cpp.Iterators
17
17
18
- from ContainerIteratorAccess it
18
+ /**
19
+ * any `.size()` check above our access
20
+ */
21
+ predicate size_checked_above ( ContainerIteratorAccess it , IteratorSource source ) {
22
+ exists ( STLContainer c , FunctionCall guardCall |
23
+ c .getACallToSize ( ) = guardCall and
24
+ guardCall = it .getAPredecessor * ( ) and
25
+ //make sure its the same container providing its size as giving the iterator
26
+ globalValueNumber ( guardCall .getQualifier ( ) ) = globalValueNumber ( source .getQualifier ( ) ) and
27
+ // and the size call we match must be after the assignment call
28
+ source .getASuccessor * ( ) = guardCall
29
+ )
30
+ }
31
+
32
+ /**
33
+ * some loop check exists like: `iterator != end`
34
+ * where a relevant`.end()` call flowed into end
35
+ */
36
+ predicate valid_end_bound_check ( ContainerIteratorAccess it , IteratorSource source ) {
37
+ exists ( STLContainer c , Loop l , ContainerIteratorAccess otherAccess , IteratorSource end |
38
+ end = c .getAnIteratorEndFunctionCall ( ) and
39
+ //flow exists between end() and the loop condition
40
+ DataFlow:: localFlow ( DataFlow:: exprNode ( end ) , DataFlow:: exprNode ( l .getCondition ( ) .getAChild ( ) ) ) and
41
+ l .getCondition ( ) .getAChild ( ) = otherAccess and
42
+ //make sure its the same iterator being checked as incremented
43
+ otherAccess .getOwningContainer ( ) = it .getOwningContainer ( ) and
44
+ //make sure its the same container providing its end as giving the iterator
45
+ globalValueNumber ( end .getQualifier ( ) ) = globalValueNumber ( source .getQualifier ( ) )
46
+ )
47
+ }
48
+
49
+ from ContainerIteratorAccess it , IteratorSource source
19
50
where
20
51
not isExcluded ( it , IteratorsPackage:: doNotUseAnAdditiveOperatorOnAnIteratorQuery ( ) ) and
21
52
it .isAdditiveOperation ( ) and
22
53
not exists ( RangeBasedForStmt fs | fs .getUpdate ( ) .getAChild * ( ) = it ) and
23
- // we get the neraby assignment
24
- not exists ( STLContainer c , FunctionCall nearbyAssigningIteratorCall , FunctionCall guardCall |
25
- nearbyAssigningIteratorCall = it .getANearbyAssigningIteratorCall ( ) and
26
- // we look for calls to size or end
27
- ( guardCall = c .getACallToSize ( ) or guardCall = c .getAnIteratorEndFunctionCall ( ) ) and
28
- // such that the call to size is before this
29
- // access
30
- guardCall = it .getAPredecessor * ( ) and
31
- // and it uses the same qualifier as the one we were just assigned
32
- nearbyAssigningIteratorCall .getQualifier ( ) .( VariableAccess ) .getTarget ( ) =
33
- guardCall .getQualifier ( ) .( VariableAccess ) .getTarget ( ) and
34
- // and the size call we match must be after the assignment call
35
- nearbyAssigningIteratorCall .getASuccessor * ( ) = guardCall
36
- )
54
+ source = it .getANearbyAssigningIteratorCall ( ) and
55
+ not size_compare_bounds_checked ( source , it ) and
56
+ not valid_end_bound_check ( it , source ) and
57
+ not size_checked_above ( it , source )
37
58
select it , "Increment of iterator may overflow since its bounds are not checked."
0 commit comments