Chinaunix首页 | 论坛 | 博客
  • 博客访问: 314439
  • 博文数量: 45
  • 博客积分: 2079
  • 博客等级: 上尉
  • 技术积分: 464
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-03 16:57
文章分类

全部博文(45)

文章存档

2015年(1)

2013年(1)

2012年(9)

2011年(2)

2010年(32)

分类: C/C++

2012-02-27 14:48:56

今天看到一个漏洞cve-2011-3026,恰好与整数溢出有关。
   “libpng图形库存在整数溢出漏洞,可能导致使用该库解码png的应用软件崩溃或执行任意代码。受影响的软件包括firefox、Thunderbird、google chome等。”
【自:http://qoop.org/security/poc/cve-2011-3026.png】

这里,先不讨论这个漏洞的内容,先介绍如何预防。

来自:C缺陷与陷阱3.9节
c语言中存在两类整数算术运算,有符号运算与无符号运算。在无符号算术运算中,没有所谓的“溢出”一说:所有的无符号运算都是以2的n次方为模,这里的n是结果中的位数。如果算术运算符的一个操作数为有符号整数,另一个为无符号整数,那么有符号整数会被转换成无符号整数,“溢出”也不可能发生。但是,当两个操作数都是有符号数时,溢出就有可能发生,而且溢出的结果是未定义的。当一个运算的结果发生溢出时,做出任何假设都是不安全的。
 
假如a和b是两个非负整型变量,我们需要检查a+b是否会溢出,一种想当然的办法是这样:
if( a + b < 0 )
{
    complain();
}
这并不能正常运行。当a+b确实发生溢出时,所有关于结果如何的假设都不再可靠。例如,在某些机器上,加法运算将设置一个内部寄存器为四种状态之一:正、负、零、溢出。在这种机器上,c编译器完全有理由这样来实现上面的例子,即a与b相加,然后检查内部寄存器的标志是否为“负”。当加法操作发生溢出时,这个内部寄存器的状态是溢出而不是负,那么if的语句的检查就会失败。
 
一种正确的方式是将a和b都强制转换为无符号整数:
if( ( unsigned )a + ( unsigned )b > INT_MAX )
{
    complain();
}
此处的INT_MAX是一个已定义的常量,代表可能的最大整数值。ANSI C标准在中定义了INT_MAX。不需要用到无符号算术运算的另外一种可行办法是:
if( a > INT_MAX - b )
{
    complain();
}
【摘自:http://blog.csdn.net/zhghost/article/details/5286338】
另外,还找到一种写法:
    
使这个特殊的测试能够成功的一个正确的方法是依赖于无符号算术的良好定义,即要在有符号和无符号之间进行转换: 

if((int)((unsigned)a + (unsigned)b) < 0) 
    complain(); 
阅读(3735) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~