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

时间:2017-03-28 09:19:41

标签: c string security

设置:

鉴于此类代码:

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]

它将前2个字符更改为hi并且不添加\ 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. 如果我的预期是错误的理解,哪一部分?
  3. 注意:

    现在,我理解这种未定义的行为应该避免,但我从试图理解可能在给定代码上使用的所有可能漏洞的角度提出这个问题。

    我不是在寻找正确的编码习惯。我正在寻找对究竟出了什么问题的理解。

    编辑1

    我确实理解文档说它的未定义行为,从开发人员的角度来看,必须避免鼻子恶魔的可能性。

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

1 个答案:

答案 0 :(得分:3)

  

在我看来,myString是一个指向内存中分配点的指针,如下所示:

one-to-one

也许在你的脑海里确实如此,实际上它看起来像这样:

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

事实上,正如评论所说,角色不是随机的,而是不确定的。很可能它们将是以前堆叠帧的残余,但你不知道。

当你在堆栈上分配一个char数组时,没有输入任何nul字节。它只是将堆栈指针递增4并且它就是它。

修改

对不起,我没有读完整个问题就跳了进去。

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

上面的行复制了一个h然后是一个i然后停止,因为它复制了两个字符。如果它是明智的,它只会复制h然后复制strncpy(myString, "hi", 2); ,但它不是。

\0是一个奇怪的功能,可能应该被托付给地狱的火热坑。它一直到第一个字符串的末尾,然后从第二个字符串和终止strncat添加最多n个字符。 n与您要复制的缓冲区的大小无关,也可能因此而超出。

\0

不能保证您的第一个字符串在任何地方都有strncat(myString, "h123", 2); (如前所述),因此它会将h和1复制到不确定的内存位置。