Strcat堆叠粉碎行为
当运行以下故意破坏堆栈的代码时,strcat会将source的值精确复制十次Strcat堆叠粉碎行为,c,gcc,memory,stack,strcat,C,Gcc,Memory,Stack,Strcat,当运行以下故意破坏堆栈的代码时,strcat会将source的值精确复制十次 #include <stdio.h> #include <stdlib.h> int main() { char a[16]; char b[16]; char c[32]; strcpy(a, "abcdefghijklmnop"); printf("a = %s\nb = %s\nc = %s\n\n", a, b, c); strcpy
#include <stdio.h>
#include <stdlib.h>
int main() {
char a[16];
char b[16];
char c[32];
strcpy(a, "abcdefghijklmnop");
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcpy(b, "ABCDEFGHIJKLMNOP");
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcpy(c, b);
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcat(c, b);
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
return 0;
}
#包括
#包括
int main(){
chara[16];
charb[16];
charc[32];
strcpy(a,“abcdefghijklmnop”);
printf(“a=%s\nb=%s\nc=%s\n\n”,a、b、c);
strcpy(b,“ABCDEFGHIJKLMNOP”);
printf(“a=%s\nb=%s\nc=%s\n\n”,a、b、c);
strcpy(c,b);
printf(“a=%s\nb=%s\nc=%s\n\n”,a、b、c);
strcat(c,b);
printf(“a=%s\nb=%s\nc=%s\n\n”,a、b、c);
返回0;
}
输出:
a=abcdefghijklmnop b=c=
a=abcdefghijklmnopABCDEFGHIJKLMNOP b=ABCDEFGHIJKLMNOP c=
a=ABCDefghijklmnopabc defghijklmnopabc defghijklmnop b=
ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP c=ABCDEFGHIJKLMNOP
a=
ABCDEfghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc
b=
ABCDEfghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc
c=
ABCDEfghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc defghijklmnopabc
**检测到堆栈崩溃*:./strcpytest已终止
建筑参数:
gcc-O0-g3-Wall-c-F消息长度=0
代码在x86_64体系结构上运行
为什么它只连接十次?我使用gcc编译器得到如下输出:
a = abcdefghijklmnop
b =
c =
a = abcdefghijklmnopABCDEFGHIJKLMNOP
b = ABCDEFGHIJKLMNOP
c =
a = abcdefghijklmnopABCDEFGHIJKLMNOP
b = ABCDEFGHIJKLMNOP
c = ABCDEFGHIJKLMNOP
a =
b = ABCDEFGHIJKLMNOP
c = ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP
这是因为您没有为terminator提供所需的大小。试试看:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char a[17];
char b[17];
char c[33];
strcpy(a, "abcdefghijklmnop");
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcpy(b, "ABCDEFGHIJKLMNOP");
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcpy(c, b);
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
strcat(c, b);
printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);
return 0;
}
#包括
#包括
#包括
int main(){
chara[17];
charb[17];
charc[33];
strcpy(a,“abcdefghijklmnop”);
printf(“a=%s\nb=%s\nc=%s\n\n”,a、b、c);
strcpy(b,“ABCDEFGHIJKLMNOP”);
printf(“a=%s\nb=%s\nc=%s\n\n”,a、b、c);
strcpy(c,b);
printf(“a=%s\nb=%s\nc=%s\n\n”,a、b、c);
strcat(c,b);
printf(“a=%s\nb=%s\nc=%s\n\n”,a、b、c);
返回0;
}
现在一切都好了。
感谢Baldrick。如果您的平台使用内存保护并使其堆栈向下扩展,如x86(),则选择任何堆栈位置并从那里写入递增地址(如字符串…)意味着您不必沿着堆栈扩展的方向,而要从堆栈的原点开始,最终,你会在一个非映射的保护页面上看到它并死掉,在这种情况下,你会收到你提到的错误消息 错误消息可以并可以通过这种方式进行个性化设置,以提示发生了什么 旁白:改变任何东西都可能改变代码的行为,因为平台没有义务这样做。
旁白:令人震惊的是,
strcpy(c,b)
的行为就好像它没有覆盖从b
开始并在c
终止的字符串的终止符一样。对于重叠字符串,strcpy()和strcat()的行为是未定义的。因此,您对c[]的两次写入都是可疑的,您不仅在测试破坏堆栈,还测试了编译器对这种未定义行为的处理
我希望strcpy(c,b)行失败,但实现必须在覆盖c开头的尾随零之前以某种方式获得b的长度。例如,如果它从最后一个字节复制到第一个字节,就会发生这种情况
strcat(c,b)可以以更直接的方式实现。也许十倍的数据就足以达到终止它的极限
如果您只想测试损坏堆栈,请不要使用这些方法。相反,只需使用一个数组,并使用循环写入它的末尾,例如“for(i=0;i<1000000;i++)c[i]='h';”我假设为x86或x86_64。对吗?请在您的问题中添加关键信息。在另一个系统上使用以前版本的gcc(Kali,gcc 4.2?)可以得到您提到的输出。问题中提到的输出是通过在Ubuntu上使用GCC4.8.2实现的。如果它取决于编译器,也就是说。你应该给空终止符留出空间。这是一个故意破坏堆栈的代码。问题是关于strcat的行为。strcat行为的原因是因为终止字符。C假定字符串是带有终止空字符的字符数组。此空字符的ASCII值为0,可以表示为0或“\0”。此值用于标记字符串中有意义数据的结束。如果缺少此值,许多C字符串函数将继续处理超过有意义数据结尾的数据,并且通常超过字符数组本身的结尾,直到在内存中找到零字节为止@贾汉:请阅读实际问题。而且,它从未找到任何0字节,因为它以前会覆盖它们。