CS.LOCRET.RET
函数返回局部变量的地址
使用之前释放的内存可能会产生任意数目的不利后果,从损坏有效数据到执行任意代码都有可能,具体取决于缺陷的实例化和时间。造成数据损坏最简单的方式中就有系统重用已释放的内存。释放后使用在 C# 中是一种罕见的情况,因为 C# 带有一个内部垃圾回收器。如果仍出现对内存的引用,该垃圾回收器并不会释放内存,但在不安全的块中则可能发生这种情况。CS.LOCRET 检查器系列会查找其中的不安全函数会为块范围之外的局部变量地址提供访问权限的实例,这会导致悬空指针或释放后使用等问题。
CS.LOCRET.RET 检查器会查找其中的函数通过返回语句中的表达式来返回局部变量地址的实例。
漏洞与风险
局部变量分配在堆栈上,因此当函数返回指向变量的指针时,它返回的是堆栈地址。该地址在从函数中返回后将无效,因此访问该地址将可能导致无法预料的应用程序行为,通常会导致程序崩溃。
出现释放后使用错误有两个常见且有些重叠的原因:
- 错误条件和其他异常情况。
- 负责释放内存的那部分程序混淆不清。
漏洞代码示例
复制
using System.IO;
namespace Example
{
class Program
{
unsafe static int* aaa()
{
int *aux = stackalloc int[3];
return aux; //@ CS.LOCRET.RET
}
static void Main(string[] args)
{
unsafe {
int *a = aaa(); // 'a' points to freed memory
}
}
}
}
Klocwork 在第 9 行报告 CS.LOCRET.RET 缺陷,其中函数 aaa 会返回局部变量 aux 的地址。