整数溢出就是对整数操作时产生了超过表示范围的数值
溢出:在C中有符号整数溢出是未定义的行为,编译器的做法是回绕或陷阱??
回绕:数据表示范围的上界和下界形成一个闭环。上界+1=下界,下界-1=上界
截断:将一个较大宽度的数存入一个宽度小的操作数中,高位发生截断
无符号整数表示
有符号整数表示
造成整数溢出的情况:
1、未限制范围
2、错误的类型转换
错误的类型转换
void init(int size){ if (size < MAX_ARRAY_SIZE){ array = malloc(size); } } //malloc里所需的参数类型是size_t(无符号整数),而传入的却是int类型。假设size为负数,那么经过类型转换(int转为unsigned int)并且回绕后,size将变成一个巨大的数。 修复方案:把int size改成size_t size
截断错误
int main(int argc, char *argv[]) { unsigned short int total; total = strlen(argv[1]) + strlen(argv[[2]) + 1; char *buff = (char * )malloc(total); strcpy(buff, argv[1]); strcat(buff, argv[2]); } //乍一看,动态分配了缓冲区大小,很安全 //仔细看total赋值的语句,将size_t(unsigned int)类型赋值给unsigned short int类型,属于较大宽度的数存入一个宽度小的数,只要strlen(argv[1]) + strlen(argv[[2])大于unsigned short int所能取到的最大值,经过高位截断后,缓冲区大小必然比实际的小 //实际输入比缓冲区大,造成了缓冲区溢出漏洞
修复方案: plan A. 限制输入字符的个数 plan B. total定义为更大宽度的数据类型
整数逻辑错误
int *table = NULL; int insert_in_table(int pos, int value){ //在table数组pos位置插入value if(!table){ table = (int *)malloc(sizeof(int) * 100) } if(pos > 99){ return -1; } table[pos] = value; return 0; }
//pos是int类型,且程序没有对数组的下界做限制 //假设pos为负数,table[pos] = value会将value写入内存中table数组之前的位置,造成内存的任意写漏洞 修复方案: plan A. 同时检查上界和下界 plan B. 将pos声明成无符号整数
总结
严格选择整数类型。
整数有明确的范围定义,可以阻止可能引起整数溢出的非常大或非常小的数据进入系统。