未经验证的本地指针运算¶
ID: cs/unvalidated-local-pointer-arithmetic
Kind: problem
Security severity: 9.3
Severity: warning
Precision: high
Tags:
- security
- external/cwe/cwe-119
- external/cwe/cwe-120
- external/cwe/cwe-122
- external/cwe/cwe-788
Query suites:
- csharp-code-scanning.qls
- csharp-security-extended.qls
- csharp-security-and-quality.qls
如果外部用户可以提供自己的虚方法实现,则在指针运算中使用虚方法调用的结果而不进行验证是危险的。例如,如果分析的项目作为库或框架分发,则最终用户可以提供一个返回任何值的新实现。
建议¶
在执行指针运算之前始终验证虚方法调用的结果,以避免在分配的缓冲区边界之外进行读写。
示例¶
在此示例中,我们使用 PossiblyOverridableClass
的实例写入数组的给定元素,以确定要写入哪个元素。
在第一种情况下,调用 GetElementNumber
方法,并且在指针运算中使用结果而不进行任何验证。如果用户可以定义 PossiblyOverridableClass
的子类型,则他们可以创建返回无效元素编号的 GetElementNumber
实现。这将导致在 charArray
的边界之外发生写入。
在第二种情况下,存储 GetElementNumber
的结果,并确认它在数组的边界内。请注意,仅检查它是否小于长度是不够的。我们还必须确保它大于零,以防止写入缓冲区之前和之后的位置。
public class PossiblyOverridable
{
public virtual int GetElementNumber()
{
// By default returns 0, which is safe
return 0;
}
}
public class PointerArithmetic
{
public unsafe void WriteToOffset(PossiblyOverridable possiblyOverridable,
char[] charArray)
{
fixed (char* charPointer = charArray)
{
// BAD: Unvalidated use of virtual method call result in pointer arithmetic
char* newCharPointer = charPointer + possiblyOverridable.GetElementNumber();
*newCharPointer = 'A';
// GOOD: Check that the number is viable
int number = possiblyOverridable.GetElementNumber();
if (number >= 0 && number < charArray.Length)
{
char* newCharPointer2 = charPointer + number;
*newCharPointer = 'A';
}
}
}
}