为什么这个字符串不会溢出缓冲区?

时间:2015-12-01 03:02:58

标签: c linux macos

我在mac和linux上运行了这段代码:

#include <stdio.h>
#include <string.h>

int main (int argc, char *argv[]){

int value = 5;
char buffer_one[8], buffer_two[8];

strcpy(buffer_one, "one");
strcpy(buffer_two, "two");

printf("[BEFORE] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
printf("[BEFORE] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
printf("[BEFORE] value is at %p and is %i (0x%08x)\n", &value, value, value);

printf("\n[STRCPY] copying %i bytes into buffer two\n\n", strlen(argv[1]));
strcpy(buffer_two, argv[1]); 

printf("[AFTER] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
printf("[AFTER] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
printf("[AFTER] value is at %p and is %i (0x%08x)\n", &value, value, value);
}

在mac上,如果我输入“1234567890”作为命令行参数,那么90会溢出到缓冲区1中,因为8个字节的缓冲区超过了2。

但是,如果我在Linux系统上运行它,则需要更多字符来溢出缓冲区。为什么我可以逃避在Linux中执行缓冲区?

另外作为附注,在两个系统上,整个字符串仍然会在缓冲区2中打印,而只在缓冲区1中打印溢出的项目。为什么会这样?为什么剩下的角色不会只是去下一个呢?如果这个问题没有得到很好的表达,那就是一个例子:

如果我在我的Mac上输入1234567890,则1234567890将在缓冲区2中打印,而90将在缓冲区1中打印。即使它已经溢出,90怎么仍然适合缓冲区2。 (这与linux上的概念相同,但溢出需要10个以上的字节)

1 个答案:

答案 0 :(得分:1)

在这两种情况下,都存在缓冲区溢出。缓冲区溢出只是调用未定义的行为。在某些情况下,它似乎完全正常,不会产生崩溃或段错误。

例如,内存分配器(在这种情况下为堆栈分配)可能会分配比协商原因所请求的内存略多的内存。在这种情况下,您实际上可能会超出缓冲区而没有任何明显的副作用,但这实际上是一件非常糟糕的事情,因为它隐藏了错误,而不是消除它。

在这种情况下,由于它涉及堆栈,因此您将覆盖堆栈中的内容,而不是为缓冲区分配的内容。如果您引入了更多变量或开始调用函数,您可能会开始注意到奇怪的副作用。在任何情况下,这都是一个非常有问题的场景,并且您希望尽可能避免缓冲区溢出。