CodeQL 文档

潜在的越界写入

ID: cpp/overrunning-write
Kind: problem
Security severity: 9.3
Severity: error
Precision: medium
Tags:
   - reliability
   - security
   - external/cwe/cwe-120
   - external/cwe/cwe-787
   - external/cwe/cwe-805
Query suites:
   - cpp-security-extended.qls
   - cpp-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

程序执行缓冲区复制或写入操作,但对复制的大小没有上限,并且似乎某些输入会导致在这种情况下发生缓冲区溢出。除了导致程序不稳定之外,还存在一些技术可能允许攻击者利用此漏洞执行任意代码。

建议

始终控制缓冲区复制和缓冲区写入操作的长度。应使用 strncpy 而不是 strcpy,使用 snprintf 而不是 sprintf,并且在其他情况下应优先使用“n 变体”函数。

示例

void sayHello(uint32_t userId)
{
	char buffer[18];

	// BAD: this message overflows the buffer if userId >= 10000
	sprintf(buffer, "Hello, user %d!", userId);

	MessageBox(hWnd, buffer, "New Message", MB_OK);
}

在此示例中,对 sprintf 的调用将写入一个 14 个字符(包括终止空字符)的消息以及将 `userId` 转换为字符串的长度,写入到一个只有 18 个字符空间的缓冲区中。因此,如果 `userId` 大于或等于 `10000`,则最后的字符会溢出缓冲区,导致未定义的行为。

要解决此问题,应进行以下更改

  • 通过使用编译时常量声明缓冲区来控制缓冲区的大小。

  • 最好将对 sprintf 的调用替换为 snprintf,并使用定义的缓冲区常量大小或 `sizeof(buffer)` 作为要写入的最大长度。这将防止缓冲区溢出。

  • 或者,如果预期 `userId` 小于 `10000`,则在 `userId` 超出范围时返回或抛出错误。

  • 否则,请考虑将缓冲区大小至少增加到 25 个字符,以便无论 `userId` 的值是多少,消息都能正确显示。

参考

  • ©GitHub 公司
  • 条款
  • 隐私