为什么 strcpy 的这种使用被认为是不好的?

Deg*_*egH 2 c buffer strcpy

我发现了以下一段C代码,标记为 BAD(又名缓冲区溢出错误)。问题是我不太明白为什么?输入字符串长度在分配等之前被捕获。

char *my_strdup(const char *s)
{
    size_t len = strlen(s) + 1;
    char *c = malloc(len);
    if (c) {
        strcpy(c, s);  // BAD
    }
    return c;
}
Run Code Online (Sandbox Code Playgroud)

评论更新:

  • “BAD”标记不精确,代码还不错,效率不高是的,有风险(如下)是的,
  • 为什么有风险?+1在 strlen() 调用之后需要安全地分配堆上的空间,该空间也将保留字符串终止符 ( '\0')

zwo*_*wol 5

您的示例函数中没有错误。

但是,为了让未来的读者(无论是人类还是机械)清楚地知道不存在错误,您应该将调用替换strcpymemcpy

char *my_strdup(const char *s)
{
    size_t len = strlen(s) + 1;
    char *c = malloc(len);
    if (c) {
        memcpy(c, s, len);
    }
    return c;
}
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,len都会分配字节并len复制字节,但memcpy这一事实对读者来说更加清晰。

  • `memcpy` 也不会浪费时间在原始字符串中查找 `\0`,因此 `memcpy` 有可能比使用 `strcpy` 更便宜。 (5认同)
  • 我认为“memcpy”让读者更清楚。毫无疑问,我们可以复制“len”字符。就我个人而言,如果我注意到那里有“strcpy”,我将不得不花两倍的时间查看代码。“_为什么?_”我会想。“_自从我们上面数完之后,有发生什么事情吗?_” - 只有多读一段时间后,我才能确定没有什么可疑的事情发生。 (2认同)
  • @yano我想我要说的关于“strcpy”的具体内容是,我还没有遇到过这样的情况:通过切换到其他函数(通常但并非总是,memcpy 或 snprintf)无法使使用 strcpy 的正确代码变得更清晰)。 (2认同)