14
14
import cpp
15
15
import codingstandards.cpp.cert
16
16
import codingstandards.cpp.Iterators
17
+ import semmle.code.cpp.controlflow.Dominance
17
18
18
19
/**
19
20
* any `.size()` check above our access
20
21
*/
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
22
+ predicate sizeCheckedAbove ( ContainerIteratorAccess it , IteratorSource source ) {
23
+ exists ( ContainerAccessWithoutRangeCheck:: ContainerSizeCall guardCall |
24
+ strictlyDominates ( guardCall , it ) and
25
25
//make sure its the same container providing its size as giving the iterator
26
26
globalValueNumber ( guardCall .getQualifier ( ) ) = globalValueNumber ( source .getQualifier ( ) ) and
27
27
// and the size call we match must be after the assignment call
@@ -30,16 +30,22 @@ predicate size_checked_above(ContainerIteratorAccess it, IteratorSource source)
30
30
}
31
31
32
32
/**
33
- * some loop check exists like: `iterator != end`
33
+ * some guard exists like: `iterator != end`
34
34
* where a relevant`.end()` call flowed into end
35
35
*/
36
- predicate valid_end_bound_check ( ContainerIteratorAccess it , IteratorSource source ) {
37
- exists ( STLContainer c , Loop l , ContainerIteratorAccess otherAccess , IteratorSource end |
36
+ predicate validEndBoundCheck ( ContainerIteratorAccess it , IteratorSource source ) {
37
+ exists (
38
+ STLContainer c , BasicBlock b , GuardCondition l , ContainerIteratorAccess otherAccess ,
39
+ IteratorSource end
40
+ |
38
41
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
42
+ //guard controls the access
43
+ l .controls ( b , _) and
44
+ b .contains ( it ) and
45
+ //guard is comprised of (anything flowing to) end check and an iterator access
46
+ DataFlow:: localFlow ( DataFlow:: exprNode ( end ) , DataFlow:: exprNode ( l .getChild ( _) ) ) and
47
+ l .getChild ( _) = otherAccess and
48
+ //make sure its the same iterator being checked in the guard as accessed
43
49
otherAccess .getOwningContainer ( ) = it .getOwningContainer ( ) and
44
50
//make sure its the same container providing its end as giving the iterator
45
51
globalValueNumber ( end .getQualifier ( ) ) = globalValueNumber ( source .getQualifier ( ) )
52
58
it .isAdditiveOperation ( ) and
53
59
not exists ( RangeBasedForStmt fs | fs .getUpdate ( ) .getAChild * ( ) = it ) and
54
60
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 )
61
+ not sizeCompareBoundsChecked ( source , it ) and
62
+ not validEndBoundCheck ( it , source ) and
63
+ not sizeCheckedAbove ( it , source )
58
64
select it , "Increment of iterator may overflow since its bounds are not checked."
0 commit comments