C语言 如果我在没有空终止符的情况下插入字符串会发生什么?



>SET UP:

给定这种代码:

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

这将打印:

KU�
hiU�
hiU�h1

我所期望的:

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

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

它将一个空指针添加到字符串开头之后的第四个位置的内存

之后:

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

它将前 2 个字符更改为 hi,并且不添加 \0

在 strncat 之后:

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

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

我所期望的没有发生。

问题:

  1. 里面印的是什么?
  2. 如果我所期望的是错误的理解,哪一部分?

注意:

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

我不是在寻找正确的编码实践。我正在寻找对到底出了什么问题的理解。

编辑 1

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

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

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

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

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

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

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

在堆栈上分配 char 数组时,不会输入 NUL 字节。它只是将堆栈指针增加 4,仅此而已。

编辑

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

strncpy(myString, "hi", 2);

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

strncat是一个奇怪的功能,可能应该被扔进地狱的火坑里。它一直到第一个字符串的末尾,然后从第二个字符串和一个终止中加到 n 个字符。n 与要复制到的缓冲区的大小无关,因此可以溢出。

strncat(myString, "h123", 2);

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

最新更新