为啥 strcpy 在 C 中不安全? [复制]

Posted

技术标签:

【中文标题】为啥 strcpy 在 C 中不安全? [复制]【英文标题】:Why is strcpy unsafe in C? [duplicate]为什么 strcpy 在 C 中不安全? [复制] 【发布时间】:2014-06-12 14:46:42 【问题描述】:

我是初学者,现在正在学习如何在 C 中复制字符串。

这是我刚刚遇到的一个问题:

每次我尝试使用“strcpy”命令从字符串 1 复制到字符串 2 时,Visual Studio 2013 都会给我一条错误/警告消息,指出“strcpy”不安全,并建议我改用 strcpy_s。

你能解释一下为什么 strcpy 使用起来不安全吗?还有什么比 strcpy 更安全?

这是我的代码:

#include<stdio.h>
#include<string.h>
main()

    char str1[] = "Copy a string.";
    char str2[15];
    char str3[15];
    int i;

    /* with strcpy() */
    strcpy(str2, str1);
    /* Without strcpy() */
    for (i = 0; str1[i]; i++)
        str3[i] = str1[i];
    str3[i] = '\0';
    /* Display str2 and str3 */
    printf("The content of str2: %s\n", str2);
    printf("The content of str3: %s\n", str3);
    return 0;

附:我在 Windows 7 64 位终极版上使用 Visual Studio 2013 64 位终极版。 感谢您的宝贵时间!

【问题讨论】:

实际上,当 MSVC 编译器告诉您 strncpy 也是不安全的时,事情变得很有趣。他们希望您使用strncpy_s,它添加了第二个参数来指示大小并修改strncpy 的标准行为,以便截断的字符串附加一个空终止符。不用说,所有这些_s 函数都是非标准的,我通常只是定义某个预处理器定义来消除该警告。 strcpy() 不是不安全的,微软是不安全的。 c99标准的支持在哪里?顺便说一句:“不安全”是 PHB 的说法,最好忽略它。 BTW2:main 的原型是:int main(void)int main(int argc, char **argv) 是的,微软也想拥抱、扩展、消灭 C。 strcpy() 是一个非常安全的函数(不像,比如说,gets())在右手中。不幸的是,很多程序员编码不好,然后要求“更安全”的语言。懦夫。 ...因为 C 字符串本质上是不安全的:( 建议:char str2[sizeofstr1]; 并避免使用像 15 这样的幻数。让编译器完成计算所需大小的工作。 【参考方案1】:

strcpy 无法知道目标缓冲区有多大(即没有长度参数),因此使用它的草率编程可能会导致缓冲区溢出并损坏其他内存。这种溢出可能导致崩溃、奇怪的行为,并且可能被恶意软件作者利用。

顺便说一句,看看带有长度参数的 strncpy。需要注意的一个问题是,如果缓冲区太小,strncpy 将不会终止字符串,因此它本身就很危险。

回答您的评论/问题 - 这将取决于上下文。如果您知道缓冲区足够大(例如,您在上一行中以正确的大小分配了它),请使用 strcpy。如果有任何溢出的可能性,则使用 strncpy 并确保将缓冲区中的最后一个位置设置为空。请注意,应该非常宽泛地解释“任何可能性”——除非前面的五六行足以表明安全,否则请使用 strncpy。

另请参阅上面关于 strncpy_s 的 Andon 评论。最后,如果您确实使用 strcpy,您可能需要添加 #pragma 以在该位置取消警告。

【讨论】:

您有什么建议可以使程序更健壮?感谢您的回答! 请不要使用strncpy 作为strcpy 的“更安全”的替代品。见this answer。【参考方案2】:

这是您的原始代码:

int main() 
    char str1[] = "Copy a string.";
    char str2[15];

    strcpy(str2, str1);

现在,三天后,您去编辑这段代码。你已经意识到你实际上需要写消息"This code is copying a string."

int main() 
    char str1[] = "This code is copying a string.";
    char str2[15];

    strcpy(str2, str1);

但是,您现在不小心引入了缓冲区溢出。

strcpy_s 需要str2 长度的额外参数。这样,虽然您可能无法将整个字符串放入新缓冲区,但不会导致未定义的行为。

【讨论】:

【参考方案3】:

与 strncpy 和 strcpy_s 不同,strcpy 不会对目标缓冲区进行任何长度检查,这可能会导致堆栈溢出,从而允许攻击者在被利用时执行恶意代码或只是破坏您的应用程序

【讨论】:

注意:strncpy 也不保证字符串终止。

以上是关于为啥 strcpy 在 C 中不安全? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

strcpy和memcpy的区别

为啥浮点数据类型在没有类型转换 4.7 的情况下在此代码中不起作用? [复制]

C - 为啥 strcpy() 是必要的

memcpy和strcpy的区别

c语言编程中字符串复制函数编程程序出现错误,这是怎么回事?

strcpy函数用法