struct函数测试
源代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int a[2];
double d;
} struct_t;
double fun(int i) {
volatile struct_t s;
s.d = 3.14;
s.a[i] = 1073741824; /* Possibly out of bounds */
return s.d; /* Should be 3.14 */
}
int main(int argc, char *argv[]) {
int i = 0;
if (argc >= 2)
i = atoi(argv[1]);
double d = fun(i);
printf("fun(%d) --> %.10f\n", i, d);
return 0;
}
/*
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 0
fun(0) --> 3.1400000000
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 1
fun(1) --> 3.1400000000
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 2
fun(2) --> 3.1399998665
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 3
fun(3) --> 2.0000006104
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 4
fun(4) --> 3.1400000000
段错误 (核心已转储)
*/
测试结果:
我的程序在入到第六个数据时会显示溢出,程序会终止。
学习心得:
栈溢出有时可能无法避免,它往往会造成很大的危害。
为了减少‘栈溢出’的出现几率,我们平时在编写代码的时候要时刻注意栈上的缓冲区的使用方式,熟悉关于栈缓冲区的各种操作API(使用最为频繁的就是字符串操作函数)的正确使用方式。
相关:
gcc编译器的stack保护机制:
*** stack smashing detected ***:
<unknown> terminated
已放弃 (核心已转储)
该提示信息就是gcc提供的栈溢出保护机制在检测到程序存在缓冲区溢出时所打印出来的提示信息。
通过查看gcc的使用手册,我们可以知道该报机制为gcc的-fstack-protector一系列选项所提供的缓冲区溢出检测机制。下面为该机制的原理介绍:
当-fstack-protector启用时,当其检测到缓冲区溢出时(例如,缓冲区溢出攻击)时会立即终止正在执行的程序,并提示其检测到缓冲区存在的溢出的问题。这种机制是通过在函数中的易被受到攻击的目标上下文添加保护变量来完成的。这些函数包括使用了allcoa函数以及缓冲区大小超过8bytes的函数(此处不是很明白,上面的例子缓冲区大小为5同样触发了该机制)。这些保护变量在进入函数的时候进行初始化,当函数退出时进行检测,如果某些变量检测失败,那么会打印出错误提示信息并且终止当前的进程。