1313 */
1414
1515import go
16+ private import semmle.go.controlflow.Guards
1617
1718newtype TIndex =
1819 VariableIndex ( DataFlow:: SsaNode v ) { v .getAUse ( ) = any ( DataFlow:: ElementReadNode e ) .getIndex ( ) } or
@@ -41,21 +42,23 @@ DataFlow::CallNode arrayLen(DataFlow::SsaNode array) {
4142}
4243
4344/**
44- * Gets a condition that checks that `index` is less than or equal to `array.length`.
45+ * Holds if `guard` evaluating to `branch` checks that `index` is less than or
46+ * equal to `array.length`.
4547 */
46- ControlFlow :: ConditionGuardNode getLengthLEGuard ( Index index , DataFlow:: SsaNode array ) {
47- result . ensuresLeq ( getAUse ( index ) , arrayLen ( array ) , 0 )
48+ predicate lengthLeGuard ( Guard guard , boolean branch , Index index , DataFlow:: SsaNode array ) {
49+ guardEnsuresLeq ( guard , branch , getAUse ( index ) , arrayLen ( array ) , 0 )
4850 or
4951 exists ( int i , int bias | index = ConstantIndex ( i ) |
50- result . ensuresLeq ( getAUse ( ConstantIndex ( i + bias ) ) , arrayLen ( array ) , bias )
52+ guardEnsuresLeq ( guard , branch , getAUse ( ConstantIndex ( i + bias ) ) , arrayLen ( array ) , bias )
5153 )
5254}
5355
5456/**
55- * Gets a condition that checks that `index` is not equal to `array.length`.
57+ * Holds if `guard` evaluating to `branch` checks that `index` is not equal to
58+ * `array.length`.
5659 */
57- ControlFlow :: ConditionGuardNode getLengthNEGuard ( Index index , DataFlow:: SsaNode array ) {
58- result . ensuresNeq ( getAUse ( index ) , arrayLen ( array ) )
60+ predicate lengthNeGuard ( Guard guard , boolean branch , Index index , DataFlow:: SsaNode array ) {
61+ guardEnsuresNeq ( guard , branch , getAUse ( index ) , arrayLen ( array ) )
5962}
6063
6164/**
@@ -78,23 +81,24 @@ predicate isRegexpMethodCall(DataFlow::MethodCallNode c) {
7881}
7982
8083from
81- ControlFlow :: ConditionGuardNode cond , DataFlow:: SsaNode array , Index index ,
82- DataFlow :: ElementReadNode ea , BasicBlock bb
84+ Guard cond , boolean branch , DataFlow:: SsaNode array , Index index , DataFlow :: ElementReadNode ea ,
85+ BasicBlock bb
8386where
8487 // there is a comparison `index <= len(array)`
85- cond = getLengthLEGuard ( index , array ) and
88+ lengthLeGuard ( cond , branch , index , array ) and
8689 // there is a read from `array[index]`
8790 elementRead ( ea , array , index , bb ) and
8891 // and the read is guarded by the comparison
89- cond .dominates ( bb ) and
92+ cond .controls ( bb , branch ) and
9093 // but the read is not guarded by another check that `index != len(array)`
91- not getLengthNEGuard ( index , array ) .dominates ( bb ) and
94+ not exists ( Guard ne , boolean neBranch |
95+ lengthNeGuard ( ne , neBranch , index , array ) and ne .controls ( bb , neBranch )
96+ ) and
9297 // and it is not additionally guarded by a stronger index check
93- not exists ( Index index2 , int i , int i2 |
98+ not exists ( Index index2 , int i , int i2 , Guard g2 , boolean b2 |
9499 index = ConstantIndex ( i ) and index2 = ConstantIndex ( i2 ) and i < i2
95100 |
96- getLengthLEGuard ( index2 , array ) . dominates ( bb )
101+ lengthLeGuard ( g2 , b2 , index2 , array ) and g2 . controls ( bb , b2 )
97102 ) and
98103 not isRegexpMethodCall ( array .getInit ( ) )
99- select cond .getCondition ( ) ,
100- "Off-by-one index comparison against length may lead to out-of-bounds $@." , ea , "read"
104+ select cond , "Off-by-one index comparison against length may lead to out-of-bounds $@." , ea , "read"
0 commit comments