1414import cpp
1515import codingstandards.cpp.cert
1616import codingstandards.cpp.Iterators
17+ import semmle.code.cpp.controlflow.Dominance
1718
1819/**
1920 * any `.size()` check above our access
2021 */
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
2525 //make sure its the same container providing its size as giving the iterator
2626 globalValueNumber ( guardCall .getQualifier ( ) ) = globalValueNumber ( source .getQualifier ( ) ) and
2727 // and the size call we match must be after the assignment call
@@ -30,16 +30,22 @@ predicate size_checked_above(ContainerIteratorAccess it, IteratorSource source)
3030}
3131
3232/**
33- * some loop check exists like: `iterator != end`
33+ * some guard exists like: `iterator != end`
3434 * where a relevant`.end()` call flowed into end
3535 */
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+ |
3841 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
4349 otherAccess .getOwningContainer ( ) = it .getOwningContainer ( ) and
4450 //make sure its the same container providing its end as giving the iterator
4551 globalValueNumber ( end .getQualifier ( ) ) = globalValueNumber ( source .getQualifier ( ) )
5258 it .isAdditiveOperation ( ) and
5359 not exists ( RangeBasedForStmt fs | fs .getUpdate ( ) .getAChild * ( ) = it ) and
5460 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 )
5864select it , "Increment of iterator may overflow since its bounds are not checked."
0 commit comments