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

原创 2016年08月28日 16:33:13
规则:

确保无符号整数运算不产生回绕,如果底层整数表示无法表示无符号整数运算的结果,该值可能发生回绕。在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/
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

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

规则1: 不通过链接创建通用字符串。 C11标准:如果匹配通用字符名称的字符序列由符号链接生成,将产生未定义行为。 #define assign(uc1,uc2,val) uc1##uc...

c++编码规范(二)

3 格式化输出安全 规则3.1:格式化输出函数的格式化参数和实参类型必须匹配 说明:使用格式化字符串应该小心,确保格式字符和参数在数据类型上的匹配。格式字符和参数之间的不匹配会导致未定义的行为。大...
  • mct123
  • mct123
  • 2014年07月24日 09:12
  • 1804

从零开始做远控 第十一篇 命令行控制

如果你从没看过这系列教程请点击:从零开始做远控 简介篇 命令行控制 这两节我们要编写用CMD指令控制客户端的部分。 这一节编写客户端: CmdSpy类: 1.创建...

从零开始做远控 第七篇 键盘监控

键盘监控: 那么快就到来第七节了,这两节我会跟大家讲讲怎么实时窃取客户端的每一个键盘输入,然后发送到服务端。 这一节我们会先做客户端方面的编程。 KeyboardSpy类: 1.现在在客户端创建一...

安全编码实践三:C/C++静态代码分析工具Prefast

《程序员》5月文章。申明。文章仅代表个人观点,与所在公司无任何联系。 概述   在前面的安全编码实践的文章里,我们讨论了GS编译选项和数据执行保护DEP功能。 结论是GS和DEP可以有效的缓解缓存溢出...

安全编码实践三:C/C++静态代码分析工具Prefast

《程序员》5月文章。申明。文章仅代表个人观点,与所在公司无任何联系。   概述    在前面的安全编码实践的文章里,我们讨论了GS编译选项和数据执行保护DEP功能。 结论是GS和DEP可...

安全编码实践三:C/C++静态代码分析工具Prefast

概述 在前面的安全编码实践的文章里,我们讨论了GS编译选项和数据执行保护DEP功能。 结论是GS和DEP可以有效的缓解缓存溢出类型的安全漏洞的危害。关于这个结论,有两个大家需要值得...

《c/c++商用工程之道》代码实现之2_锁_多线程安全的变量

6.2  锁对象  p225 #ifdef WIN32 #include #define MUTEX CRITICAL_SECTION #define MUTEXINIT(m) ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C/C++ 代码安全(三)
举报原因:
原因补充:

(最多只允许输入30个字)