针对容器长度的差一比较¶
ID: cs/index-out-of-bounds
Kind: problem
Security severity:
Severity: error
Precision: high
Tags:
- reliability
- correctness
- logic
- external/cwe/cwe-193
Query suites:
- csharp-security-and-quality.qls
针对集合、字符串或数组的索引操作应使用至多小于长度 1 的索引。如果要访问的索引与长度进行比较时小于或等于长度 (<=
),而不是小于长度 (<
),则该索引可能会超出范围。
建议¶
将潜在索引与长度进行比较时,使用小于 (<
) 而不是小于或等于 (<=
)。对于遍历数组或集合中每个元素的循环,建议使用 foreach
语法,而不是遍历显式索引。
示例¶
以下示例显示了两种方法,它们用于标识值是否出现在以逗号分隔的值列表中。
在第一个示例中,使用索引变量 - i
- 的循环用于遍历以逗号分隔的列表中的元素。但是,循环的终止条件错误地指定为 i <= values.Length
。如果 i
等于 values.Length
,则此条件将成功,但循环体中的访问 values[i]
将失败,因为索引超出范围。
一种可能的解决方案是用 i < values.Length
替换 i <= values.Length
。但是,C# 中的数组也可以在 foreach
循环中使用。这在第二个示例中显示。这避免了完全指定索引的需要,因此可以防止索引超出范围的错误。
using System.IO;
using System;
class ContainerLengthOffByOne
{
public static boolean BadContains(string searchName, string names)
{
string[] values = names.Split(',');
// BAD: index could be equal to length
for (int i = 0; i <= values.Length; i++)
{
// When i = length, this access will be out of bounds
if (values[i] == searchName)
{
return true;
}
}
}
public static boolean GoodContains(string searchName, string names)
{
string[] values = names.Split(',');
// GOOD: Avoid using indexes, and use foreach instead
foreach (string name in values)
{
if (name == searchName)
{
return true;
}
}
}
}
参考¶
常见弱点枚举:CWE-193。