Skip to content

Commit e86d08b

Browse files
authored
Merge pull request #22678 from owen-mc/go/fix/length-comparison-duplicates
Go: fix some duplicate results in `go/index-out-of-bounds`
2 parents b476fdd + 8c3c029 commit e86d08b

3 files changed

Lines changed: 26 additions & 5 deletions

File tree

‎go/ql/src/InconsistentCode/LengthComparisonOffByOne.ql‎

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ ControlFlow::ConditionGuardNode getLengthLEGuard(Index index, DataFlow::SsaNode
5151
)
5252
}
5353

54+
predicate isDominatingLengthLEGuard(
55+
ControlFlow::ConditionGuardNode guard, Index index, DataFlow::SsaNode array, BasicBlock bb
56+
) {
57+
guard = getLengthLEGuard(index, array) and
58+
guard.dominates(bb)
59+
}
60+
5461
/**
5562
* Gets a condition that checks that `index` is not equal to `array.length`.
5663
*/
@@ -81,19 +88,22 @@ from
8188
ControlFlow::ConditionGuardNode cond, DataFlow::SsaNode array, Index index,
8289
DataFlow::ElementReadNode ea, BasicBlock bb
8390
where
84-
// there is a comparison `index <= len(array)`
85-
cond = getLengthLEGuard(index, array) and
8691
// there is a read from `array[index]`
8792
elementRead(ea, array, index, bb) and
88-
// and the read is guarded by the comparison
89-
cond.dominates(bb) and
93+
// and it is guarded by a comparison `index <= len(array)`
94+
isDominatingLengthLEGuard(cond, index, array, bb) and
95+
// and report the innermost guard that establishes the comparison
96+
not exists(ControlFlow::ConditionGuardNode innerCond |
97+
isDominatingLengthLEGuard(innerCond, index, array, bb) and
98+
innerCond.getCondition().getParent+() = cond.getCondition()
99+
) and
90100
// but the read is not guarded by another check that `index != len(array)`
91101
not getLengthNEGuard(index, array).dominates(bb) and
92102
// and it is not additionally guarded by a stronger index check
93103
not exists(Index index2, int i, int i2 |
94104
index = ConstantIndex(i) and index2 = ConstantIndex(i2) and i < i2
95105
|
96-
getLengthLEGuard(index2, array).dominates(bb)
106+
isDominatingLengthLEGuard(_, index2, array, bb)
97107
) and
98108
not isRegexpMethodCall(array.getInit())
99109
select cond.getCondition(),
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
| LengthComparisonOffByOne.go:8:14:8:29 | ...<=... | Off-by-one index comparison against length may lead to out-of-bounds $@. | LengthComparisonOffByOne.go:10:6:10:14 | index expression | read |
22
| main.go:6:5:6:15 | ...<=... | Off-by-one index comparison against length may lead to out-of-bounds $@. | main.go:7:10:7:13 | index expression | read |
33
| main.go:29:5:29:14 | ...>... | Off-by-one index comparison against length may lead to out-of-bounds $@. | main.go:30:10:30:13 | index expression | read |
4+
| main.go:87:7:87:17 | ...>=... | Off-by-one index comparison against length may lead to out-of-bounds $@. | main.go:93:9:93:12 | index expression | read |

‎go/ql/test/query-tests/InconsistentCode/LengthComparisonOffByOne/main.go‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,14 @@ func f10(i int, a intintmap) int {
8383
return -1
8484
}
8585

86+
func f11(a []int) int {
87+
if !(len(a) >= 3 && // $ Alert
88+
a[0] == 0 &&
89+
a[1] == 0 &&
90+
a[2] == 0) {
91+
return -1
92+
}
93+
return a[3] // $ Source
94+
}
95+
8696
func main() {}

0 commit comments

Comments
 (0)