长度比较偏差一位¶
ID: go/index-out-of-bounds
Kind: problem
Security severity:
Severity: error
Precision: high
Tags:
- reliability
- correctness
- logic
- external/cwe/cwe-193
Query suites:
- go-security-and-quality.qls
数组、切片或字符串上的索引操作使用的索引应最多比长度小 1。如果检查要访问的索引是否小于或等于长度 (<=
),而不是小于长度 (<
),则索引可能会超出界限。
建议¶
在将潜在索引与长度进行比较时,使用小于 (<
) 而不是小于或等于 (<=
)。对于迭代每个元素的 for 循环,更好的解决方案是使用 range
循环,而不是循环访问显式索引。
示例¶
以下示例展示了一个方法,该方法检查某个值是否出现在以逗号分隔的值列表中
package main
import "strings"
func containsBad(searchName string, names string) bool {
values := strings.Split(names, ",")
// BAD: index could be equal to length
for i := 0; i <= len(values); i++ {
// When i = length, this access will be out of bounds
if values[i] == searchName {
return true
}
}
return false
}
使用索引变量 i
的循环用于迭代以逗号分隔的列表中的元素。但是,循环的终止条件被错误地指定为 i <= len(values)
。当 i
等于 len(values)
时,此条件成立,但在这种情况下,循环体中的访问权限 values[i]
将超出界限。
一种可能的解决方案是用 i < len(values)
替换 i <= len(values)
。更好的解决方案是使用 range
循环,这样就无需显式操作索引变量
package main
import "strings"
func containsGood(searchName string, names string) bool {
values := strings.Split(names, ",")
// GOOD: Avoid using indexes, use range loop instead
for _, name := range values {
if name == searchName {
return true
}
}
return true
}