dest缓冲区小于src缓冲区时的strcpy

use*_*891 5 c string buffer-overflow strcpy

我试图了解strcpy和strncpy的区别/缺点.有人可以帮忙:

void main()
{
char src[] = "this is a long string";
char dest[5];

strcpy(dest,src) ;
printf("%s \n", dest);
printf("%s \n", src);

}
Run Code Online (Sandbox Code Playgroud)

输出是:

this is a long string 
a long string 
Run Code Online (Sandbox Code Playgroud)

问题:我不明白,源sting是如何被修改的.根据解释,strcpy应该继续复制,直到它遇到'\ 0',所以它确实如此,但为什么"src"字符串被修改.

请解释.

ndi*_*dim 11

简单的答案是你(使用strcpy()调用)完成了系统规范之外的某些事情,因此当之无愧地遭受了未定义的行为.

更难的答案涉及检查系统上的具体内存布局,以及strcpy()如何在内部工作.它可能是这样的:

     N+28 "g0PP"
     N+24 "trin"
     N+20 "ng s"
     N+16 "a lo"
     N+12 " is "
src  N+08 "this"
     N+04 "DPPP"
dest N+00 "DDDD"
Run Code Online (Sandbox Code Playgroud)

字母D代表dest中的P字节,字母是填充字节,0字符是用作字符串终止符的ASCII NUL字符.

现在strcpy(dest,src)会稍微改变内存内容(假设它正确处理重叠的内存区域):

     N+28 "g0PP"
     N+24 "trin"
     N+20 "g0 s"
     N+16 "trin"
     N+12 "ng s"
src  N+08 "a lo"
     N+04 " is "
dest N+00 "this"
Run Code Online (Sandbox Code Playgroud)

即,当dest现在"包含"完整字符串"这是一个长字符串"(如果你计算溢出的内存),src现在包含一个完全不同的NUL终止字符串"一个长字符串".


eph*_*ent 7

这是缓冲区溢出和未定义的行为.

在您的情况下,似乎编译器已经放置dest并按src顺序存储在内存中.从中复制srcdest,它会继续复制到结尾dest并覆盖部分内容src.

  • 并且src和dst似乎与4个字符的倍数对齐,因此当dest为5个字符长时,新的受损src将在原始src(现在为dest)中启动8个字符. (2认同)