Chinaunix首页 | 论坛 | 博客
  • 博客访问: 486690
  • 博文数量: 53
  • 博客积分: 492
  • 博客等级: 下士
  • 技术积分: 866
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-14 15:12
文章分类

全部博文(53)

文章存档

2016年(1)

2015年(3)

2014年(17)

2013年(9)

2012年(7)

2011年(16)

我的朋友

分类: C/C++

2011-12-16 13:53:20

以前,我知道scanf很危险,使用不当,会造成非法内存访问,程序崩溃。比如:

1)  使用%s,没限定输入长度或长度不对,导致读取的字符串超出缓冲区大小。

2)  使用的格式和实际数据类型不相符;

3)  格式符个数和实际参数个数不相符;

现在,我才知道,我所知道的scanf危险,并不是它的全部。我一直以为,使用scanf读取整数、浮点数还是安全的,没想到其实也未必。比如:

#include

int main()

{

    int a = 0;

    scanf("%d", &a);

    return 0;

}

这段代码很普通吧,有谁知道这段代码其实也可能出现程序崩溃?至于你知不知道,反正我是不知道。

 

空口白话,不足为信,大家回头自己编译一下上述这段代码,然后用这条命令测试一下:

perl -e 'print "5"x2100000' | ./a.out

 

在我机器上的测试结果:

[zbc@haifen ~]$ perl -e 'print "5"x2100000' | ./a.out

Segmentation fault (core dumped)

 

GDB看到的程序堆栈:

(gdb) bt

#0  0x00657d83 in _IO_vfscanf_internal () from /lib/libc.so.6

#1  0x00660e1b in scanf () from /lib/libc.so.6

#2  0x080483a9 in main () at test_i.c:5

 

怎么办?其实改起来并不难。在每个格式符中都带上长度限定就可以了。比如上述scanf("%d", &a)改为scanf(“%50d”, &a),崩溃现象就消失了。

 

可以看出,并不是scanf往a里面写时造成了溢出,而应该是scanf内部缓冲区溢出。

 

PS:

这个问题,是我使用cppcheck时,cppcheck报告出来的一个错误。一开始我还以为有点夸张了,自己一验证,才知道原来真是这样的。

 

测试平台:

        [zbc@haifen ~]$ uname -a


        Linux haifen 2.6.11-1.1369_FC4 #1 Thu Jun 2 22:55:56 EDT 2005 i686 athlon i386 GNU/Linux


        [zbc@haifen ~]$ gcc -v


        Using built-in specs.


        Target: i386-redhat-linux


        Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,java,f95,ada --enable-java-awt=gtk --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --host=i386-redhat-linux


        Thread model: posix


        gcc version 4.0.0 20050519 (Red Hat 4.0.0-8)

阅读(2070) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~