CodeQL 文档

针对容器长度的差一比较

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

点击查看 CodeQL 存储库中的查询

针对集合、字符串或数组的索引操作应使用至多小于长度 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;
            }
        }
    }
}

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私