我的gcc版本是4.8.2,操作系统是ubuntu 14.04(64位)。 我发现有时候gcc会自动生成canary以进行缓冲区溢出保护,有时却不会。为什么?
生成canary的情况:当SIZE是4的倍数时。
#include<stdio.h>
#define SIZE 4
int main()
{
char s[SIZE];
scanf("%s", s);
return 0;
}
在使用gcc -c -g -Wa,-a,-ad后的汇编代码
...
4:a.c **** int main()
5:a.c **** {
13 .loc 1 5 0
14 .cfi_startproc
15 0000 55 pushq %rbp
16 .cfi_def_cfa_offset 16
17 .cfi_offset 6, -16
18 0001 4889E5 movq %rsp, %rbp
19 .cfi_def_cfa_register 6
20 0004 4883EC10 subq $16, %rsp
21 .loc 1 5 0
22 0008 64488B04 movq %fs:40, %rax
22 25280000
22 00
23 0011 488945F8 movq %rax, -8(%rbp)
24 0015 31C0 xorl %eax, %eax
6:a.c **** char s[SIZE];
7:a.c **** scanf("%s", s);
...
不生成canary:不是4的倍数
#include<stdio.h>
#define SIZE 2
int main()
{
char s[SIZE];
scanf("%s", s);
return 0;
}
在使用gcc -c -g -Wa,-a,-ad命令后,进行汇编
...
4:a.c **** int main()
5:a.c **** {
13 .loc 1 5 0
14 .cfi_startproc
15 0000 55 pushq %rbp
16 .cfi_def_cfa_offset 16
17 .cfi_offset 6, -16
18 0001 4889E5 movq %rsp, %rbp
19 .cfi_def_cfa_register 6
20 0004 4883EC10 subq $16, %rsp
6:a.c **** char s[SIZE];
7:a.c **** scanf("%s", s);
...
-fstack-protector
,但man页面说对于所有具有大于8字节缓冲区的函数都会生成canary,编译器为这两个缓冲区分配了16字节的空间(在你和我机器上一样),因此两个版本都应该有canary。我在相同版本的GCC上得到了不同的行为。你尝试过更大的数字吗,比如17和20? - xaizek