华为c&c++语言安全编程规范_v3.1

上传人:n**** 文档编号:96122946 上传时间:2019-08-24 格式:PDF 页数:52 大小:910.72KB
返回 下载 相关 举报
华为c&c++语言安全编程规范_v3.1_第1页
第1页 / 共52页
华为c&c++语言安全编程规范_v3.1_第2页
第2页 / 共52页
华为c&c++语言安全编程规范_v3.1_第3页
第3页 / 共52页
华为c&c++语言安全编程规范_v3.1_第4页
第4页 / 共52页
华为c&c++语言安全编程规范_v3.1_第5页
第5页 / 共52页
点击查看更多>>
资源描述

《华为c&c++语言安全编程规范_v3.1》由会员分享,可在线阅读,更多相关《华为c&c++语言安全编程规范_v3.1(52页珍藏版)》请在金锄头文库上搜索。

1、华为C 12. 13. p = p-next; 14. 15. 16. UnLock(); 17. 18. return p; 19. 程序在运行期间,函数内的局部变量保存在栈中,栈的大小是有限的。如果申请过大的静态数组,可能导致出现运 行出错。 建议在申请静态数组的时候,大小不超过0x1000。 下面的代码,buff 申请过大,导致栈空间不够,程序 发生stackoverfl ow异常。 相关指南: CERT.MEM05-C. Avoid large stack allocations 1.2 断言(ASSERT) 断言是一种除错机制,用于验证代码是否符合编码人员的预期。编码人员在开发期间应

2、该对函数的参数、代码中间 执行结果合理地使用断言机制,确保程序的缺陷尽量在测试阶段被发现。 断言被触发后,说明程序出现了不应该出 现的严重错误,程序会立即提示错误,并终止执行。 断言必须用宏进行定义,只在调试版本有效,最终发布版本不 允许出现assert函数,例如: 下面的函数VerifyUser,上层调用者会保证传进来的参数是合法的字符串,不可能出现传递非法参数的情况。因 此,在该函数的开头,加上4个ASSERT进行校验。 以下的switch,由于不可能出现default的情况,所以在default处直接调用ASSERT: 1. #define MAX_BUFF 0x1000000 2. i

3、nt Foo() 3. 4. char buffMAX_BUFF = 0; 5. . 6. 1. #include 2. #ifdef DEBUG 3. #define ASSERT(f) assert(f) 4. #else 5. #define ASSERT(f) (void)0) 6. #endif 1. BOOL VerifyUser(const char *userName, const char *password) 2. 3. ASSERT(userName != NULL); 4. ASSERT(strlen(userName) 0); 5. ASSERT(password !

4、= NULL); 6. ASSERT(strlen(password) 0); 7. . 8. 1. enum 2. COLOR_RED = 1, 3. COLOR_GREEN, 4. COLOR_BLUE 5. ; 6. . 7. switch (color) 以下代码,SendMsg是CMsg类的成员函数,socketID是成员变量,在调用SendMsg的时候必须保证socketID已经 被初始化,因此在此处用ASSERT判断socketID的合法性。 在linux内核中定义ASSERT宏,可以采用如下方式: 相关指南: CERT.MSC11-C. Incorporate diagnost

5、ic tests using assertions 规则1.2.1:断言必须使用宏定义,禁止直接调用系统提供的assert() 断言只能在调试版使用,断言被触发后,程序会立即退出,因此严禁在正式发布版本使用断言,请通过编译选项进 行控制。 错误用法如: 规则1.2.2:运行时可能会导致的错误,严禁使用断言 8. case COLOR_RED: 9. . 10. case COLOR_GREEN: 11. . 12. case COLOR_BLUE: 13. . 14. default: 15. ASSERT(0); 16. 17. 1. CMsg:CMsg() 2. 3. socketID =

6、 INVALID_SOCKET; 4. 5. int CMsg:SendMsg(const char *msg, int len) 6. 7. ASSERT(socketID != INVALID_SOCKET); 8. . 9. ret = send(socketID, msg, len, 0); 10. . 11. 1. #ifdef DEBUG 2. #define ASSERT(f) BUG_ON(!(f) 3. #else 4. #define ASSERT(f) (void)0) 5. #endif 1. int Foo(int *array, int size) 2. 3. as

7、sert(array != NULL); 4. . 5. 断言不能用于校验程序在运行期间可能导致的错误。 以下代码的所有ASSERT的用法是错误的。 规则1.2.3:严禁在断言内改变运行环境 在程序正式发布阶段,断言不会被编译进去,为了确保调试版和正式版的功能一致性,严禁在断言中使用任何赋 值、修改变量、资源操作、内存申请等操作。 例如,以下的断言方式是错误的: 建议1.2.1:不要将多条语句放在同一个断言中 为了更加准确地发现错误的位置,每一条断言只校验一个条件。 下面的断言同时校验多个条件,在断言触发的时 候,无法判断到底是哪一个条件导致的错误: 应该将每个条件分开: 1.3 函数 规则1

8、.3.1:数组作为函数参数时,必须同时将其长度作为函数的参数 通过函数参数传递数组或一块内存进行写操作时,函数参数必须同时传递数组元素个数或所传递的内存块大小,否 则函数在使用数组下标或访问内存偏移时,无法判断下标或偏移的合法范围,产生越界访问的漏洞。 以下代码中, 函数ParseMsg不知道msg的范围,容易产生内存越界访问漏洞。 1. FILE *fp = fopen(path, “r“); 2. ASSERT(fp != NULL); /文件有可能打开失败 3. char *str = (char *)malloc(MAX_LINE); 4. ASSERT(str != NULL); /

9、内存有可能分配失败 5. ReadLine(fp, str); 6. char *p = strstr(str, age=); 7. ASSERT(p != NULL); /文件中不一定存在该字符串 8. int age = atoi(p+4); 9. ASSERT(age 0); /文件内容不一定符合预期 1. ASSERT(p1 = p2); /p1被修改 2. ASSERT(i+ 1000); /i被修改 3. ASSERT(close(fd) = 0);/fd被关闭 1. int Foo(int *array, int size) 2. 3. ASSERT(array != NULL

10、5. ASSERT(size vendorID != 0) 20. . 21. 22. . 23. 1. #define ETH_ALEN 6 2. 3. static const u8 ethReservedAddrBaseETH_ALEN = .; 4. . 5. void EtherAddrCopy(unsigned char *dst, const unsigned char *src) 6. 7. dst0 = src0; 8. dst1 = src1; 9. dst2 = src2; 10. dst3 = src3; 11. dst4 = src4; 12. dst5 = src5

11、; 13. 14. 15. int AddDevice() 16. 17. unsigned char macETH_ALEN; 18. . 19. EtherAddrCopy(mac, ethReservedAddrBase); 20. . 21. 对于设计成API的函数,必须对参数进行合法性判断,严禁在API实现过程中产生CRASH。对API函数的参数进行 ASSERT操作是没有意义的。 例如,对于提供应用服务器IP的平台公共API接口这样实现是错误的: 公共接口API应当对输入参数进行代码检查: 规则1.3.3:不对内容进行修改的指针型参数,定义为const 如果参数是指针型参数,且内容

12、不会被修改,请定义为const类型。 示例: 相关指南: CERT.DCL13-C Declare function parameters that are pointers to values not changed by the function as const MISRA.C.2004.Rule 16.7 (advisory): A pointer parameter in a function prototype should be declared as pointer to const if the pointer is not used to modify the addres

13、sed object. 建议1.3.1:谨慎使用不可重入函数 不可重入函数在多线程环境下其执行结果不能达到预期效果,需谨慎使用。常见的不可重入函数包括: rand, srand getenv, getenv_s strtok strerror asctime, ctime, localtime, gmtime setlocale 1. int GetServerIP(char *ip, size_t ipSize) 2. 3. ASSERT(ip != NULL); 4. . 5. 1. int GetServerIP(char *ip, size_t ipSize) 2. 3. if (ip

14、 = NULL) 4. . 5. 6. . 7. 1. int Foo(const char *filePath) 2. 3. . 4. int fd = open(filePath, .); 5. . 6. atomic_init tmpnam mbrtoc16, c16rtomb, mbrtoc32, c32rtomb gethostbyaddr gethostbyname inet_ntoa 建议1.3.2:字符串或指针作为函数参数时,请检查参数是否为NULL 如果字符串或者指针作为函数参数,为了防止空指针引用错误,在引用前必须确保该参数不为NULL,如果上层调 用者已经保证了该参数不可

15、能为NULL,在调用本函数时,在函数开始处可以加ASSERT进行校验。 例如下面的代 码,因为BYTE *p有可能为NULL,因此在使用前需要进行判断。 下面的代码,由于p的合法性由调用者保证,对于Foo函数,不可能出现p为NULL的情况,因此加上ASSERT进行校 验。 1. int Foo(int *p, int count) 2. 3. if (p != NULL 5. 6. . 7. 8. 9. int Foo2() 10. 11. int *arr = . 12. int count = . 13. Foo(arr, count); 14. . 15. 1. int Foo(int *p, int count) 2. 3. ASSERT(p != NULL); /ASSERT is added to verify p. 4. ASSERT(count 0); 5. in

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 大杂烩/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号