mirror of
https://github.com/github/codeql.git
synced 2026-01-21 10:24:47 +01:00
56 lines
1.8 KiB
Plaintext
56 lines
1.8 KiB
Plaintext
/**
|
|
* @name Inconsistent direction of for loop
|
|
* @description A 'for' loop that increments its loop variable but checks it
|
|
* against a lower bound, or decrements its loop variable but
|
|
* checks it against an upper bound, will either stop iterating
|
|
* immediately or keep iterating indefinitely, and is usually
|
|
* indicative of a typo.
|
|
* @kind problem
|
|
* @problem.severity error
|
|
* @id go/inconsistent-loop-direction
|
|
* @tags correctness
|
|
* external/cwe/cwe-835
|
|
* @precision very-high
|
|
*/
|
|
|
|
import go
|
|
|
|
/**
|
|
* Holds if `test` bounds `v` in `direction`, which is either `"upward"`
|
|
* or `"downward"`.
|
|
*
|
|
* For example, `x < 42` bounds `x` upward, while `y >= 0` bounds `y`
|
|
* downward.
|
|
*/
|
|
predicate bounds(RelationalComparisonExpr test, Variable v, string direction) {
|
|
test.getLesserOperand() = v.getAReference() and direction = "upward"
|
|
or
|
|
test.getGreaterOperand() = v.getAReference() and direction = "downward"
|
|
}
|
|
|
|
/**
|
|
* Holds if `upd` updates `v` in `direction`, which is either `"upward"`
|
|
* or `"downward"`.
|
|
*
|
|
* For example, `++x` updates `x` upward, while `y--` updates `y`
|
|
* downward.
|
|
*/
|
|
predicate updates(IncDecStmt upd, Variable v, string direction) {
|
|
upd.getOperand() = v.getAReference() and
|
|
(
|
|
upd instanceof IncStmt and direction = "upward"
|
|
or
|
|
upd instanceof DecStmt and direction = "downward"
|
|
)
|
|
}
|
|
|
|
from ForStmt l, Variable v, string d1, string d2
|
|
where
|
|
bounds(l.getCond(), v, d1) and
|
|
updates(l.getPost(), v, d2) and
|
|
d1 != d2 and
|
|
// `for u = n; u <= n; u--` is a somewhat common idiom
|
|
not (v.getType().getUnderlyingType() instanceof UnsignedIntegerType and d2 = "downward")
|
|
select l.getPost(), "This loop counts " + d2 + ", but its variable is $@ " + d1 + ".", l.getCond(),
|
|
"bounded"
|