C 和 C++ 编程中的整数溢出
来源:互联网 发布:小青柑淘宝店导航条 编辑:程序博客网 时间:2024/05/01 04:47
一、 超越整数范围的溢出
当执行算法以计算缓冲区大小,真正的安全性漏洞会随同这些缺陷一起出现。请看下面的示例:
void func(char *b1, int c1, char *b2, int c2) {
const int MAX = 48;
if (c1 + c2 > MAX) return;
char *pBuff = new char[MAX];
memcpy(pBuff,b1,c1);
memcpy(pBuff+c1,b2,c2);
}
上面的代码看起来没有问题,但如果将 c1 和 c2 相加,结果超过 232-1,您就会意识到有问题了。例如,0xFFFFFFF0 和 0x40 相加的结果为 0x30(十进制为 48)。当这些值用于 c1 和 c2 时,加起来的和可以通过大小检查,然后代码会将大约 4GB 复制到 48 个字节的缓冲区。这样就会出现缓冲区溢出!类似于这样的许多错误都可以被利用,使攻击者将代码注入您的进程中。
那像这种问题如何解决呢?
可以在可能发生溢出的地方,加上条件判断,比如解决上面的问题, 可以写为:
If( c1 < 0 || c2 < 0 || c1 + c2 > MAX ) return;
二、 类型转换时的溢出
在一个复杂的应用程序中,一个表达式中包含了各种类型的变量,这时在运算过程中就包括了各种的默认类型转换。这个默认类型转换都是按你想的过程进行的吗? 先看如下的例子, 首先, 自己猜测一下结果:
#include <stdio.h>
int main()
{
signed short intb1, intb2;
unsigned short uintb;
long longc1, longc2;
unsigned long ulongc1, ulongc2;
longc1 = -34;
ulongc1 = 7;
uintb = 3;
intb1 = -84;
if( longc1 > ulongc1 )
printf("%ld > %lu /n", longc1, ulongc1);
else
printf("%ld < %lu /n", longc1, ulongc1);
if( longc1 > uintb )
printf("%ld > %u /n", longc1, uintb);
else
printf("%ld < %u /n", longc1, uintb);
if( intb1 > uintb )
printf(" %d > %u /n", intb1, uintb);
else
printf(" %d < %u /n", intb1, uintb);
longc2 = ulongc1 + longc1;
printf("%lu + %ld = %ld /n", ulongc1, longc1, longc2);
ulongc2 = ulongc1 + longc1;
printf("%lu + %ld = %lu /n", ulongc1, longc1, ulongc2);
if( ulongc1 + longc1 > 0)
printf("%lu + %ld > 0 /n", ulongc1, longc1);
}输出的结果是:
-34 > 7
-34 < 3
-84 < 3
7 + -34 = -27
7 + -34 = 4294967269
7 + -34 > 0
以上的程序在GCC2.9 上编译,liunx7.3上运行的结果。
从输出的结果来看,和你预期的输出结果一样吗?
也许从下面的输出结果,你能了解到问题出在那里了吗?
7 + -34 = -27
7 + -34 = 4294967269
7 + -34 > 0
是的,从中我们就可以看出, 类型转换的作用。
现在来解释一下如下表示式:
7 + -34 > 0
因为 ulongc1 是无符号数, longc1是有符号数 ,所以longc1转换为无符号相加,产生如下结果:
ulongc1 + longc1 = 4294967269
这时,自然
ulongc1 + longc1 > 0
对于longc1 > uintb 以及 intb1 > uintb 的比较过程中, 默认的转换中,都将双字节short类型(不管是有无符号)先转换为有符号四字节类型int , 再进行比较,所以才比较出正确的结果。
从以上的测试来看, 我们来看如下一段介绍默认类型转换的:
在C语言中,在进行表达式计算时,如果其中有多种类型时,一般先进行类型转换,再进行计算。默认的类型转换是从字节少向字节多的转换,有符号的向无符号类型转换。因些,如果算术运算符的一个操作数是有符号整数,另一个是无符号整数,那么有符号整数会被转换为无符号整数,计算结果自然也是无符号数。
发现其中也有不完善的地方, 因为低于四字节的类型,如char , unsigned char , short, unsigned shourt 都是先转换为int 类型,再进行计算, 数据没有丢失及溢出,因此不存在判断错误。所以要注意的就是int 以及 unsigned int混合,此时何正确进行判断呢?
只要先有符号数的范围检查:
if ((longc1 > 0)&& (longc1 > ulongc1))
{
// longc1 > ulongc1
}
- C 和 C++ 编程中的整数溢出
- C语言中的整型溢出和移位溢出
- C陷阱与缺陷-整数的溢出
- c语言中整数溢出的概念
- C C++的整数溢出陷阱
- c编程:整数的个数。
- C 溢出
- C/C++ 无符号整数加法溢出判断
- [美]Andrew Koenig -C陷阱与缺陷 - 整数溢出
- 重视C语言中的栈溢出
- C中的危险函数(缓冲区溢出)
- C#-求整数段和
- C# 中的整数溢出检查 checked 和 unchecked
- C/C++编程:整数转字符串输出
- 编程算法 - 大整数加法 代码(C)
- c编程中的问题
- c#中的异步编程
- 【C语言】整型溢出和整型提升
- GNU make 指南
- 一个不错的shell 脚本教程
- 返回值..
- 在数组中查找一个值
- Oracle数据库数据操作和控制语言详解(精华)
- C 和 C++ 编程中的整数溢出
- 在lucene中使用中文自动分词技术
- 高级 Linux 命令精通指南
- Raw Delphi
- Linux 文件命令精通指南
- 用JS限制文本框只能输入数字时的正则表达式问题!
- 无题
- 在 Linux x86 上安装 Oracle 数据库 10g
- 在 Linux x86 上安装 Oracle RAC 10g