C/C++ 代码安全(三)

来源:互联网 发布:苹果cms和海洋cms 编辑:程序博客网 时间:2024/06/05 18:16
规则:确保无符号整数运算不产生回绕,如果底层整数表示无法表示无符号整数运算的结果,该值可能发生回绕。在8086处理器上整数溢出也就仅仅会发生一个标志位修改罢了。所以我们还是要注意整数溢出发生回绕现象。
/*错误实例,这很有可能发生回绕*/void func(unsigned int ui_a,unsigned int ui_b){        unsigned int usum = ui_a + ui_b;}/*解决方法*/void func(unsigned int ui_a,unsigned int ui_b){            unsigned int sum;    if(UINT_MAX - ui_a < ui_b){        /*handle error*/    }else{        usum = ui_a + ui_b;    }    /*.......*/}
减法也是一样的道理,我们其实该关心以下加法和减法在标准中到底是如何定义的。加法:加法是在两个算数类型的操作数之间或者指向对象类型的指针和整数类型之间进行的。减法:减法是在两个算术类型操作数,指向兼容对象类型或者非限定版本的两个指针,或者指向一个对象类型的指针与整数类型之间进行的,这条规则只适用于两个算术类型操作数之间的减法。乘法:乘法在两个算术类型的操作数之间进行。回绕现象如果出现在内存分配语句中,很可能导致内存分配异常。规则:确保整数转换不会造成数据丢失或者错误解释。对于所有数值和所有可能相容实现都保证安全的唯一整数类型转换,是从整数值转换为相同符号的更宽类型。C11标准,中规定当一个整数类型被转换成一个新的非BOOL类型时,如果该值可以被新类型所表示,它就不会变化,否则,如果新的类型是无符号的,该值被重复加上或者减去新类型所能表示的值加1,直到该值处于新类型范围中。如果新类型是有符号的且该值无法用新类型表示;则结果有实现定义,或者使用实现定义符号。
void fun(){    unsigned long int u_a = local_max;    signed char sc;            sc = (signed char)u_a;      /*无符号转为有符号造成截断错误*/}void fun(){                     /*有符号转换为无符号造成符号丢失*/     signed int si = INT_MIN;    unsigned int ui = (unsigned int )si;}void fun(){                     /*数据截断导致精度损失*/    signed long int s_a =  LONG_MAX;    signed char sc = (signed char)s_a;}void time_test(){        time_t now = time(NULL);    if(now != (time_t)-1){  /*确保时间类型*/        /*do something*/    }}
规则:确保有符号整数的运算不会造成溢出。尤其是符号位问题。规则:确保除法和余数运算不会造成0除数错误。如果/ % 运算符的第二个操作数为0 ,则会造成未定义行为。被除数是类型最小负值,除数是-1.也会造成溢出。规则:不要使用负数或者不小于操作数位数对表达式进行位移。注意,算术位移和逻辑位移。规则:将指针转换为整数或者将整数转换为指针。规则:不要使用浮点变量作为循环计数器,浮点数并不能精确表示所有实数。 
void func(){    for(float x = 0.1f;x <= 1.0f;x += 0x.f){        /*这个循环只执行9次*/    }}
规则:确保浮点转换在新类型的范围之内。规则:不要形成或使用超限的指针或数组下标。主要是因为C语言不检查边界。规则:确保变长数组的大小参数在有效范围内。规则:不要进行两个不引用相同数组的指针之间的减法。不要假定变量之间一定连续在栈上存在。规则:不要在指向非数组对象的指针上加或者减一个整数。规则:保证库函数不形成无效指针。规则:不要在指针上加或者减一个按比例调整的整数。规则:不要试图修改字符串字面量,程序企图修改字符串字面量的任何部分,都会发生未定义行为。规则:保证字符串存储有足够的空间容纳字符数据和NULL 结束符。规则:不要向要求字符串参数的库函数传递非NULL结束的字符序列。规则:在转换为更大的整数尺寸之前将字符转换为unsigned char 类型。规则:字符串处理函数的实参必须可以表示为unsigned char  .这条规则的适用代码必须运行在char 数据类型定义为和 signed char 相同值域,表示和行为上。规则:不要混淆窄和宽字符串以及函数。

查看原文:http://zmrlinux.com/2016/08/28/cc-%e4%bb%a3%e7%a0%81%e5%ae%89%e5%85%a8%ef%bc%88%e4%b8%89%ef%bc%89/
0 0
原创粉丝点击