为啥 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 中不安全? [复制]的主要内容,如果未能解决你的问题,请参考以下文章