2017-03-28 22 views
-1

SET UP:如果我strncat到没有空终止符的字符串会发生什么?

鉴于这种代码:

char myString[4]; 
printf("%s\n", myString); 
strncpy(myString, "hi", 2); 
printf("%s\n", myString); 
strncat(myString, "h123", 2); 
printf("%s\n", myString); 

这将打印:

KU� 
hiU� 
hiU�h1 

我的预期:

在我的脑海里,MyString的是内存中分配点的指针,如下所示:

MEMORY: [random][random][random][\0][random][random][random].... 
PRINTED: [random][random][random][\0] 

它增加了一个空指针到所述存储器中的第四位串

函数strncpy后开始后:

MEMORY: [h][i][random][\0][random][random][random]... 
PRINTED: [h][i][random][\0] 

它改变了前两个字符是喜和不不添加\ 0

strncat函数后:

MEMORY: [h][i][random][h][1][2][3][\0]... 
PRINTED: [h][i][random][h][1][2][3][\0] 

它在字符串开始之后查找\ 0,然后删除\ 0并在末尾添加自己的字符串以及\ 0。

我的预期没有发生。

问题:

  1. 正在打印什么呢?
  2. 如果我所期望的是哪一部分是不正确的理解?

注:

现在,我明白,这不确定的行为,它应该是可以避免的,但我问从试图理解,可以在给定的使用所有可能的攻击的角度来看这个问题,码。

我不是在寻找适当的编码习惯。我正在寻找理解到底发生了什么问题。

编辑1

我也明白,文档说,它的不确定的行为,并从开发人员的角度必须恰好可以避免的可能性鼻恶魔。

但是从开发者的角度来看,这里正在发生一些事情,这可能不仅仅是一个错误,而是它可能是一个安全缺陷,可以更深入地理解,从而形成一致的漏洞利用。我希望更深层次的理解。的

+3

这是未定义的行为。任何事情都可能发生。 –

+3

myString的初始值是所有“随机”字节(或者垃圾发生在内存中),所以你的初始假设是错误的。 –

+0

你在'myString'上试过'memset'为0吗? – Gaurav

回答

3

在我的脑海里,MyString的是一个指向分配点在内存中,看起来像这样:

MEMORY: [random][random][random][\0][random][random][random].... 

也许在你的心中是这样,在现实中,它看起来就像这样:

MEMORY: [random][random][random][random][random][random][random].... 

事实上,正如评论所说,字符不是随机的,而是不确定的。他们很可能会成为以前的堆栈框架的残余,但你不知道。

当你在栈上分配一个char数组时,不会有nul个字节被放入。它只是将堆栈指针递增4,就是这样。

编辑

对不起,我跃升没有阅读的整个问题。

strncpy(myString, "hi", 2); 

上述行复制一个h然后一个i,然后停止,因为它复制了两个字符。如果它是明智的,它只会复制h,然后是\0,但事实并非如此。

strncat是一个奇怪的功能,应该可能委托给地狱的火坑。它沿着第一个字符串结尾,然后从第二个字符串中加起来n个字符,并终止\0。 n与您正在复制的缓冲区的大小无关,并且您可以为此超限。

strncat(myString, "h123", 2); 

有没有保证您的第一个字符串拥有\0任何地方(如已经讨论过),所以它会复制h与1为不确定的内存位置。

+0

谢谢。所以,如果我打印未定义的字符串很多,它可能会给我字符串长度超过4个字符,只要它从未在内存中命中空值?另外,这是我的主要/唯一的错误? – Rorschach

+1

准确地说,它不是'[random]',而是'[indeterminate]'。 –

+0

@MichaelWalz这是一个值得注意的好点。随机和不确定之间有很大的区别。 – sjsam

相关问题