一个正确使用gets的方法

gets太臭名昭著了,因为它是缓冲区溢出的最大祸根之一。连Linux Programmer’s Manual里都说:“Never use gets().”。没错,你几乎就没有能正确使用它的方法,因为它根本就不关心缓冲区到底够不够,只是一股脑地往里写数据。 如果你写了带gets的程序,gcc甚至会提示:“ warning: the `gets’ function is dangerous and should not be used.”。

可是,如果我们仔细想想,究竟有没有正确使用gets的时候?答案是肯定的。那怎么才能正确使用gets呢?其实也很简单,我们只要设置保卫页面(guard pages)来对付溢出就可以了。在Linux上,我们可以这么做:

include

include

include

int main(void){
int pagesize;
void p;
char
buf;
size_t buflen = 4;

pagesize = getpagesize();
p = mmap(NULL, 2*pagesize, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (p == MAP_FAILED) {
    perror("mmap");
    return -1;
}
if (mprotect(p, pagesize, PROT_READ|PROT_WRITE)){
    perror("mprotect");
    munmap(p, 2*pagesize);
    return -1;
}
buf = (char*)p + pagesize - buflen;

ifdef DEBUG

printf("buf=%p, p=%pn", buf, p);

endif

gets(buf);
puts(buf);
munmap(p, 2*pagesize);
return 0;

}

这时,如果写入的数据超出我们的缓冲区,程序就会收到SIGSEGV而退出。