gpt4 book ai didi

c - 如何防止 memcpy 缓冲区溢出?

转载 作者:太空狗 更新时间:2023-10-29 17:05:46 25 4
gpt4 key购买 nike

程序中有一些固定大小的二进制缓冲区,用于存储数据,memcpy 用于将缓冲区从一个缓冲区复制到另一个缓冲区。由于源缓冲区可能比目标缓冲区大,如何检测是否存在缓冲区溢出?

最佳答案

How can I detect if there is buffer overflow?

我认为您有三四个选择(给予或接受)。


首选是为memcpy 提供一个“安全”的功能。这是我在我的职权范围内对代码的要求,我会定期审计它。我还要求验证所有参数,并断言所有参数。

断言创建自调试代码。我希望开发人员编写代码;我不想让他们浪费时间调试。所以我要求他们编写 self 调试的代码。断言也很好地记录了事情,所以他们可以跳过文档。在发布版本中,ASSERT 被预处理器宏删除。

errno_t safe_memcpy(void* dest, size_t dsize, void* src, size_t ssize, size_t cnt)
{
ASSERT(dest != NULL);
ASSERT(src != NULL);
ASSERT(dsize != 0);
ASSERT(ssize != 0);
ASSERT(cnt != 0);

// What was the point of this call?
if(cnt == 0)
retrn 0;

if(dest == NULL || src == NULL)
return EINVALID;

if(dsize == 0 || ssize == 0)
return EINVALID;

ASSERT(dsize <= RSIZE_MAX);
ASSERT(ssize <= RSIZE_MAX);
ASSERT(cnt <= RSIZE_MAX);

if(dsize > RSIZE_MAX || ssize > RSIZE_MAX || cnt > RSIZE_MAX)
return EINVALID;

size_t cc = min(min(dsize, ssize), cnt);
memmove(dest, src, cc);

if(cc != cnt)
return ETRUNCATE;

return 0;
}

如果您的 safe_memcpy 返回非 0,则说明存在错误参数或潜在缓冲区溢出等错误。


第二种选择是使用 C 标准提供的“更安全”的函数。 C 通过 ISO/IEC TR 24731-1, Bounds Checking Interfaces 具有“更安全”的功能.在符合标准的平台上,您可以简单地调用 gets_ssprintf_s。它们提供一致的行为(比如始终确保字符串以 NULL 终止)和一致的返回值(比如成功时为 0 或 errno_t)。

errno_t  err = memcpy_s(dest, dsize, src, cnt);
...

不幸的是,gcc 和 glibc 不符合 C 标准。 Ulrich Drepper(glibc 维护者之一)调用边界检查接口(interface) "horribly inefficient BSD crap" ,而且它们从未被添加。


第三种选择是使用平台的“更安全”接口(interface)(如果存在)。在 Windows 上,这恰好与 ISO/IEC TR 24731-1, Bounds Checking Interfaces 中的相同。 .您还有字符串安全库。

在 Apple 和 BSD 上,memcpy 没有“更安全”的功能。但是您确实有更安全的字符串函数,例如 strlcpystrlcat 和 friend 。


在 Linux 上,您的第四个选择是使用 FORTIFY_SOURCE。 FORTIFY_SOURCE 使用“更安全”的高风险函数变体,例如 memcpystrcpygets。当编译器可以推断出目标缓冲区大小时,它会使用更安全的变体。如果副本超过目标缓冲区大小,则程序调用 abort()。如果编译器无法推断出目标缓冲区大小,则不会使用“更安全”的变体。

要禁用 FORTIFY_SOURCE 进行测试,您应该使用 -U_FORTIFY_SOURCE-D_FORTIFY_SOURCE=0 编译程序。

关于c - 如何防止 memcpy 缓冲区溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12210451/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com