缓冲区溢出跳过换行符

时间:2014-03-16 20:36:05

标签: c buffer

我正在尝试堆栈缓冲区溢出

struct something {
    char A[8];
    unsigned short B;
};

int main(void) {
    struct something st;
    st.B = 1979;
    strcpy(st.A, "excessive");
    printf("%d\n", st.B);
    printf("%s", st.A);
    return 0;
}

这非常有效。我得到了输出

101
excessive

但是,字符串"过度"有10个字符,包括空终止符,因此即使我将数组更改为char A[9],它也应该溢出。但在这种情况下它不会溢出并输出B的原始值。为什么会这样? \ 0在哪里?

2 个答案:

答案 0 :(得分:0)

内存分配遵循所谓的自然对齐;即,内存中的任何项目至少与其自身大小的倍数对齐。

unsigned short B大小为2个字节(在x86上)。因此,它的内存地址与2的倍数对齐。当你有A[8]时,数组会消耗偶数个字节;并且BA的最后一个字节之后的字节开始。这就是你的字符串溢出B内存的方式。

但是,A[9]需要奇数个字节,因此B无法从下一个字节开始,因为它会破坏对齐。编译器将插入一个填充字节,以确保B的地址是2的倍数。这个额外的字节为\0字符占用空间,从而幸免于缓冲区溢出。< / p>

答案 1 :(得分:0)

'\0'被写入结构成员B。这也解释了为什么在第一个101语句中得到printf的原因。它正在工作,因为strcpy没有粉碎堆栈。这意味着它不会超出为堆栈上的结构变量st分配的内存。 C标准保证结构成员按声明的顺序存储。但是,如有必要,在每个struct成员之前添加填充,以确保正确对齐。

此处,strcpy来电

strcpy(st.A, "excessive");

覆盖结构成员数组A,并在结构成员B中写入。幸运的是,此处st结构的大小足以让"excessive"复制字符串文字strcpy。在我的32位计算机上,sizeof st10strcpy复制的字节数也是10。这也解释了为什么声明

printf("%d\n", st.B);

打印101而非1979,因为其内容已被strcpy调用覆盖。如果您尝试复制长度超过9字符的字符串,或者如果您在char a[B];之后声明了数组unsigned short B;,那么对strcpy的调用将尝试非法内存访问导致未定义的行为,并且很可能由于段错误导致程序崩溃。

此外,'\0'称为空字符或空字节,而不是'\n'的换行符。