Strcat堆叠粉碎行为

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

当运行以下故意破坏堆栈的代码时,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(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字节,因为它以前会覆盖它们。