欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    华为C&C语言安全编程规范_V3.1.docx

    • 资源ID:97286534       资源大小:313.51KB        全文页数:47页
    • 资源格式: DOCX        下载积分:20金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要20金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    华为C&C语言安全编程规范_V3.1.docx

    华为C&C+语言安全编程规范Huawei C&C+ Secure Coding StandardV3.1华为技术有限公司 版权所有 侵权必究目录0 前言目的适用范围 攻击者思维安全编码基本思想外部数据定义术语定义1 基础要求1.1 变量规则1.1.1:指针变量、表示资源描述符的变量、BOOL变量声明必须赋予初值规则1.1.2:指向资源句柄或描述符的变量,在资源释放后立即赋予新值规则1.1.3:类的成员变量必须在构造函数中赋予初值规则1.1.4:严禁对指针变量进行sizeof操作建议1.1.1:尽量使用const建议1.1.2:全局变量的访问如果涉及多个线程,必须加锁 建议1.1.3:同一个函数内,局部变量所占用的空间不要过大1.2 断言(ASSERT)规则1.2.1:断言必须使用宏定义,禁止直接调用assert函数规则1.2.2:运行时可能会导致的错误,严禁使用断言规则1.2.3:严禁在断言内改变运行环境建议1.2.1:不要将多条语句放在同一个断言中1.3 函数规则1.3.1:数组作为函数参数时,必须同时将其长度作为函数的参数规则1.3.2:严禁对公共接口API函数的参数进行ASSERT操作规则1.3.3:不对内容进行修改的指针型参数,定义为const建议1.3.1:谨慎使用不可重入函数建议1.3.2:字符串或指针作为函数参数时,请检查参数是否为NULL建议1.3.3:在函数的开始处对参数进行ASSERT操作(API除外)1.4 循环规则1.4.1:循环必须有退出条件1.5 异常机制规则1.5.1:禁用C+异常机制1.6 类规则1.6.1:如果有构造函数,则必须有析构函数规则1.6.2:构造函数内不能做任何有可能失败的操作规则1.6.3:严禁在构造函数中创建线程规则1.6.4:严禁出现 delete this操作规则1.6.5:如果类的公共接口中返回类的私有数据地址,则必须加const类型建议1.6.1:尽量避免定义public成员1.7 安全退出规则1.7.1:禁用atexit函数规则1.7.2:严禁调用kill、TerminateProcess函数终止其他进程规则1.7.3:禁用pthread_exit、ExitThread函数建议1.7.1:禁用exit、ExitProcess函数(main函数除外)建议1.7.2:禁用abort函数2 字符串/数组操作规则2.1:确保有足够的存储空间规则2.2:对字符串进行存储操作,确保字符串有0结束符规则2.3:外部数据作为数组索引时必须确保在数组大小范围内规则2.4:外部输入作为内存操作相关函数的复制长度时,需要校验其合法性规则2.5:调用格式化函数时,禁止format参数由外部可控规则2.6:调用格式化函数时,format中参数的类型与个数必须与实际参数类型一致3 正确使用安全函数规则3.1:正确设置安全函数中的destMax参数规则3.2:禁止不正确地重定义或封装安全函数规则3.3:禁止用宏重命名安全函数规则3.4:禁止自定义安全函数规则3.5:必须检查安全函数返回值,并进行正确的处理4 整数规则4.1:整数之间运算时必须严格检查,确保不会出现溢出、反转、除0规则4.2:整型表达式比较或赋值为一种更大类型之前必须用这种更大类型对它进行求值规则4.3:禁止对有符号整数进行位操作符运算规则4.4:禁止整数与指针间的互相转化规则4.5:禁止对指针进行逻辑或位运算(&&、|、!、>>、<<、&、|)规则4.6:循环次数如果受外部数据控制,需要校验其合法性5 内存规则5.1:内存申请前,必须对申请内存大小进行合法性校验规则5.2:内存分配后必须判断是否成功规则5.3:禁止引用未初始化的内存 规则5.4:内存释放之后立即赋予新值规则5.5:禁止使用realloc()函数规则5.6:禁止使用alloca()函数申请栈上内存6 不安全函数规则6.1:禁止外部可控数据作为system、popen、WinExec、ShellExecute、execl, execlp, execle, execv, execvp、CreateProcess等进程启动函数的参数规则6.2:禁止外部可控数据作为dlopen/LoadLibrary等模块加载函数的参数规则6.3:禁止使用外部数据拼接SQL命令规则6.4:禁止在信号处理例程中调用非异步安全函数规则6.5:禁用setjmp/longjmp规则6.6:禁止使用内存操作类危险函数7 文件输入/输出规则7.1:创建文件时必须显式指定合适的文件访问权限规则7.2:必须对文件路径进行规范化后进行使用规则7.3:不要在共享目录中创建临时文件建议7.1:在进行文件操作时避免引起竞争条件8 敏感信息处理规则8.1:禁用rand函数产生用于安全用途的伪随机数规则8.2:内存中的敏感信息使用完毕后立即清0规则8.3:严禁使用string类存储敏感信息附录A SQL注入相关的特殊字符附录B 命令注入相关的特殊字符附录C 危险函数及替换的安全函数列表附录D 异步安全的函数列表参考资料0 前言目的本规范旨在加强编程人员在编程过程中的安全意识,建立编程人员的攻击者思维,养成安全编码的习惯,编写出安全可靠的代码。适用范围C/C+语言编程人员都应遵循本规范所规定的内容。攻击者思维编程过程中应该时刻保持以下的假设:1. 程序所处理的所有外部数据都是不可信的攻击数据2. 攻击者时刻试图监听、篡改、破坏程序运行环境、外部数据安全编码基本思想基于以上的假设,得出安全编码基本思想:1. 程序在处理外部数据时必须经过严格的合法性校验 编程人员在处理外部数据过程中必须时刻保持这种思维意识,不能做出任何外部数据符合预期的假设,外部数据必须经过严格判断后才能使用。编码人员必须在这种严酷的攻击环境下通过遵守这一原则保证程序的执行过程符合预期结果。2. 尽量减少代码的攻击面 代码的实现应该尽量简单,避免与外部环境做多余的数据交互,过多的攻击面增加了被攻击的概率,尽量避免将程序内部的数据处理过程暴露到外部环境。3. 通过防御性的编码策略来弥补潜在的编码人员的疏忽 粗心是人类的天性。由于外部环境的不确定性,以及编码人员的经验、习惯的差异,代码的执行过程很难达到完全符合预期设想的情况。因此在编码过程中必须采取防御性的策略,尽量缓解由于编码人员疏忽导致的缺陷。这些措施包括:变量声明应该赋予初值谨慎使用全局变量禁用功能复杂、易用错的函数禁用易用错的编译器/操作系统的机制小心处理资源访问过程不要改变操作系统的运行环境(创建临时文件、修改环境变量、创建进程等)严格的错误处理合理使用调试断言(ASSERT)外部数据定义文件(包括程序的配置文件)注册表网络环境变量命令行用户输入(包括命令行、界面)用户态数据(对于内核程序)进程间通信(包括管道、消息、共享内存、socket、RPC等)函数参数(对于API)全局变量(在本函数内,其他线程会修改全局变量)术语定义规则:编程时必须遵守的约定。建议:编程时必须加以考虑的约定。例外:指规范不适用的某些特殊场景。"规则"的例外应该是极少的。(特别说明:为聚焦于每项规则及建议内容重点表达的内容,示例代码中通常省略了安全函数的返回值检查以及其他与重点表述内容无关的检查)1 基础要求1.1 变量规则1.1.1:指针变量、表示资源描述符的变量、BOOL变量声明必须赋予初值1. SOCKET s = INVALID_SOCKET;2. unsigned char *msg = NULL;3. BOOL success = FALSE;4. int fd = -1;变量声明赋予初值,可以避免由于编程人员的疏忽导致的变量未初始化引用。示例:以下代码,由于变量声明未赋予初值,在最后free的时候出错。1.2.3.4.5.6.7.8.9.char *message; / 错误!必须声明为 char *message = NULL;.if (condition) message = (char *)malloc(len);.if (message != NULL) free(message);/如果condition未满足,会造成free未初始化的内存。10. 例外1: 对全局变量,静态变量,在编译阶段自动初始化为0或者等于NULL,不用在定义时强制初始化。 例如:1. OS_SEC_BSS TICK_ENTRY_FUNC2. OS_SEC_BSS volatile UINT643. OS_SEC_BSS volatile UINT644. OS_SEC_BSS volatile UINT64g_pfnTickTaskEntry; g_ullSleepTime; g_ullSleepBegin;g_ullSleepEnd;相关指南:CERT.EXP33-C. Do not read uninitialized memoryMISRA.C.2004. Rule 9.1 (required): All automatic variables shall have been assigned a value before being used.规则1.1.2:指向资源句柄或描述符的变量,在资源释放后立即赋予新值资源释放后,对应的变量应该立即赋予新值,防止后续又被重新引用。如果释放语句刚好在变量作用域的最后一句,可以不进行赋值。示例:1. SOCKET s = INVALID_SOCKET;2. unsigned char *msg = NULL;3. int fd = -1;4. .5. closesocket(s);6. s = INVALID_SOCKET;7. .8. free(msg);9. msg = (unsigned char *)malloc(.); /msg变量又被赋予新值10. .11. close(fd);12. fd = -1;13. .相关指南:CERT.MEM01-C. Store a new value in pointers immediately after free()规则1.1.3:类的成员变量必须在构造函数中赋予初值如果类中声明了变量,则必须在构造函数中对变量进行赋值。示例:1. class CMsg 2. public:3. CMsg();4. CMsg();5. protected:6. int size;7. unsigned char *msg;8. ;9.10. CMsg:CMsg()11. 12. size = 0;13. msg = NULL;14. 规则1.1.4:严禁对指针变量进行sizeof操作编码人员往往由于粗心,将指针当做数组进行sizeof操作,导致实际的执行结果与预期不符。 下面的代码,buer和path分别是指针和数组,编码人员想对这2个内存进行清0操作,但由于编码人员的疏忽,第5行代码,将内存大小误写成了sizeof,与预期不符。1. char *buffer = (char *)malloc(size);2. char pathMAX_PATH = 0;3. .4. memset(path, 0, sizeof(path);5. memset(buffer, 0, sizeof(buffer);如果要判断当前的指针类型大小,请使用sizeof(char *)的方式。相关指南:CERT.ARR01-C. Do not apply the sizeof operator to a pointer when taking the size of an array建议1.1.1:尽量使用const在变量声明前加const关键字,表示该变量不可被修改,这样就可以利用编译器进行类型检查,将代码的权限降到更低。 例如下面是不好的定义:1. float pi = 3.14159f;应当这样定义:1. const float PI = 3.14159f;相关指南:CERT.DCL00-C. Const-qualify immutable objects建议1.1.2:全局变量的访问如果涉及多个线程,需要考虑多线程竞争条件问题应该尽可能减少全局变量的使用,如果多个线程会访问到该全局变量,则访问过程必须加锁。 以下代码中,g_list是全局变量,对链表进行搜索操作时,在while循环语句的前后加锁。1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.ItemList *g_list = NULL;ItemList *SearchList(const char *name)Lock();ItemList *p = g_list;while (p != NULL) if (strcmp(p->name, name) = 0) break;p = p->next;UnLock();return p;19. 性能敏感的代码,请考虑采用原子操作或者无锁算法。相关指南:CERT.CON43-C. Do not allow data races in multithreaded code MITRE.CWE-366, Race condition within a thread建议1.1.3:同一个函数内,局部变量所占用的空间不要过大1. #define MAX_BUFF 0x10000002. int Foo()3. 4.char buffMAX_BUFF = 0;5.6. 程序在运行期间,函数内的局部变量保存在栈中,栈的大小是有限的。如果申请过大的静态数组,可能导致出现运行出错。 建议在申请静态数组的时候,大小不超过0x1000。 下面的代码,bu申请过大,导致栈空间不够,程序发生stackoverow异常。相关指南:CERT.MEM05-C. Avoid large stack allocations1.2 断言(ASSERT)断言是一种除错机制,用于验证代码是否符合编码人员的预期。编码人员在开发期间应该对函数的参数、代码中间执行结果合理地使用断言机制,确保程序的缺陷尽量在测试阶段被发现。 断言被触发后,说明程序出现了不应该出现的严重错误,程序会立即提示错误,并终止执行。 断言必须用宏进行定义,只在调试版本有效,最终发布版本不允许出现assert函数,例如:1. #include <assert.h>2. #ifdef DEBUG3. #define ASSERT(f) assert(f)4. #else5. #define ASSERT(f) (void)0)6. #endif下面的函数VerifyUser,上层调用者会保证传进来的参数是合法的字符串,不可能出现传递非法参数的情况。因此,在该函数的开头,加上4个ASSERT进行校验。1. BOOL VerifyUser(const char *userName, const char *password)2. 3. ASSERT(userName != NULL);4. ASSERT(strlen(userName) > 0);5. ASSERT(password != NULL);6. ASSERT(strlen(password) > 0);7. .8. 以下的switch,由于不可能出现default的情况,所以在default处直接调用ASSERT:1. enum 2. COLOR_RED = 1,3. COLOR_GREEN,4. COLOR_BLUE5. ;6. .7. switch (color) 8. case COLOR_RED:9. .10. case COLOR_GREEN:11. .12. case COLOR_BLUE:13. .14. default: 15. ASSERT(0);16.17. 以下代码,SendMsg是CMsg类的成员函数,socketID是成员变量,在调用SendMsg的时候必须保证socketID已经被初始化,因此在此处用ASSERT判断socketID的合法性。1. CMsg:CMsg()2. 3. socketID = 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. 在linux内核中定义ASSERT宏,可以采用如下方式:1. #ifdef DEBUG2. #define ASSERT(f) BUG_ON(!(f)3. #else4. #define ASSERT(f) (void)0)5. #endif相关指南:CERT.MSC11-C. Incorporate diagnostic tests using assertions规则1.2.1:断言必须使用宏定义,禁止直接调用系统提供的assert()断言只能在调试版使用,断言被触发后,程序会立即退出,因此严禁在正式发布版本使用断言,请通过编译选项进行控制。 错误用法如:1. int Foo(int *array, int size)2. 3. assert(array != NULL);4. .5. 规则1.2.2:运行时可能会导致的错误,严禁使用断言1. FILE *fp = fopen(path, "r");2. ASSERT(fp != NULL);/文件有可能打开失败3. char *str = (char *)malloc(MAX_LINE);4. ASSERT(str != NULL);/内存有可能分配失败5. ReadLine(fp, str);6. char *p = strstr(str, 'age=');7. ASSERT(p != NULL);/文件中不一定存在该字符串8. int age = atoi(p+4);9. ASSERT(age > 0);/文件内容不一定符合预期断言不能用于校验程序在运行期间可能导致的错误。 以下代码的所有ASSERT的用法是错误的。规则1.2.3:严禁在断言内改变运行环境在程序正式发布阶段,断言不会被编译进去,为了确保调试版和正式版的功能一致性,严禁在断言中使用任何赋值、修改变量、资源操作、内存申请等操作。 例如,以下的断言方式是错误的:1. ASSERT(p1 = p2);/p1被修改2. ASSERT(i+ > 1000);/i被修改3. ASSERT(close(fd) = 0);/fd被关闭建议1.2.1:不要将多条语句放在同一个断言中为了更加准确地发现错误的位置,每一条断言只校验一个条件。 下面的断言同时校验多个条件,在断言触发的时候,无法判断到底是哪一个条件导致的错误:1. int Foo(int *array, int size)2. 3. ASSERT(array != NULL && size > 0 && size < MAX_SIZE);4. .5. 应该将每个条件分开:1. int Foo(int *array, int size)2. 3. ASSERT(array != NULL);4. ASSERT(size > 0);5. ASSERT(size < MAX_SIZE);6. .7. 1.3 函数规则1.3.1:数组作为函数参数时,必须同时将其长度作为函数的参数通过函数参数传递数组或一块内存进行写操作时,函数参数必须同时传递数组元素个数或所传递的内存块大小,否则函数在使用数组下标或访问内存偏移时,无法判断下标或偏移的合法范围,产生越界访问的漏洞。 以下代码中,函数ParseMsg不知道msg的范围,容易产生内存越界访问漏洞。1. int ParseMsg(BYTE *msg)2. 3.4. 5. .6. size_t len = .7. BYTE *msg = (BYTE *)malloc(len); /此处分配的内存块等同于字节数组8. .9. ParseMsg(msg);10. .正确的做法是将msg的大小作为参数传递到ParseMsg中,如下代码:1. int ParseMsg(BYTE *msg, size_t msgLen)2. 3. ASSERT(msg != NULL);4. ASSERT(msgLen != 0);5. .6. 7. .8. size_t len = .9. BYTE *msg = (BYTE *)malloc(len);10. .11. ParseMsg(msg, len);12. .下面的代码,msg是固定长度的数组,也必须将数组大小作为函数的参数:1. int ParseMsg(BYTE *msg, size_t msgLen)2. 3. ASSERT(msg != NULL);4. ASSERT(msgLen != 0);5. .6. 7. .8. BYTE msgMAX_MSG_LEN = 0;9. .10. ParseMsg(msg, sizeof(msg);11. .对于const char *类型的参数,它的长度是通过'0'的位置计算出来,不需要传长度参数。1. int SearchName(const char *name)2. 3. .4. 5. .6. char *name = getName(.);7. .8. int ret = SearchName(name);9. .1. int SaveName(char *name, size_t len, const char *inputName)2. 3.4.ret = strcpy_s(name, len, inputName);5.6. 7. .8. char nameNAME_MAX = 0;9. .10. int ret = SaveName(name, sizeof(name), inputName);11. .如果参数是char *,且参数作为写内存的缓冲区,那么必须传入其缓冲区长度。如:如果函数仅对字符串中的特定字符进行一对一替换,或者删除字符串中的特定字符,这时对字符数组的访问不会超过原字符串边界,因此这类函数不需要传待修改的字符串长度。1.2.3.4.5.6.7.8.9.10.11.12.13.14.void FormatPathSeparator(char *path)unsigned int i = 0;if (path = NULL) return;while (pathi != '0') if ('' = pathi) pathi = '/' i+;15. 例外1: 对于const struct *类型的数组入参,如果它的长度可以通过特定元素值判断结尾,那么可以不传递结构体数组的长度。1. struct DevType 2. int vendorID;3. int deviceID;4. int subDevice;5. ;6. .7. const struct DevType cardIds = 8. CARD_ID, PCI_DEV_T1, PCI_ANY_ID ,9. CARD_ID, PCI_DEV_T2, PCI_ANY_ID ,10. CARD_ID, PCI_DEV_T3, PCI_ANY_ID ,11. 0, 12. ;13. .14. int BuildCardQueue(const struct DevType *cards)15. 16.17.18.19.int index = 0;ASSERT(cards != NULL);while (cardsindex->vendorID != 0) 20.21.22.23. 例外2: 对固定长度的数组,如果用数组的头地址作为子函数参数,由于性能原因,可以不用传递其长度。 下例中,EtherAddrCopy()函数仅用于MAC地址的赋值,不会用于其他地方,且长度是可保证的,其拷贝使用的下标(或偏移)没有外部数据的影响。由于性能高度敏感,因此这里没有传入目的缓冲区dst的长度。1.2.3.4.5.6.7.8.9.10.11.12.#define ETH_ALEN 6static const u8 ethReservedAddrBaseETH_ALEN = .;.void EtherAddrCopy(unsigned char *dst, const unsigned char *src)dst0 = src0;dst1 = src1;dst2 = src2;dst3 = src3;dst4 = src4;dst5 = src5;13. 14.15. int AddDevice()16. 17. unsigned char macETH_ALEN;18. .19. EtherAddrCopy(mac, ethReservedAddrBase);20. .21. 相关指南:CERT.ARR38-C. Guarantee that library functions do not form invalid pointers CERT.API00-C. Functions should validate their parametersMITRE. CWE-119, Improper Restriction of Operations within the Bounds of a Memory BuerMITRE.CWE-121, Stack-based Buer Overow MITRE.CWE-123, Write-what-where Condition MITRE.CWE-125, Out-of-bounds ReadMITRE.CWE-805, Buer Access with Incorrect Length Value规则1.3.2:严禁对公共接口API函数的参数进行ASSERT操作对于设计成API的函数,必须对参数进行合法性判断,严禁在API实现过程中产生CRASH。对API函数的参数进行1. int GetServerIP(char *ip, size_t ipSize)2. 3.ASSERT(ip != NULL);4.5. ASSERT操作是没有意义的。 例如,对于提供应用服务器IP的平台公共API接口这样实现是错误的:公共接口API应当对输入参数进行代码检查:1. int GetServerIP(char *ip, size_t ipSize)2. 3. if (ip = NULL) 4. .5.6.7. 规则1.3.3:不对内容进行修改的指针型参数,定义为const如果参数是指针型参数,且内容不会被修改,请定义为const类型。示例:1. int Foo(const char *filePath)2. 3. .4. int fd = open(filePath, .);5. .6. 相关指南:CERT.DCL13-C Declare function parameters that are pointers to values not changed by the function as constMISRA.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 addressed object.建议1.3.1:谨慎使用不可重入函数不可重入函数在多线程环境下其执行结果不能达到预期效果,需谨慎使用。常见的不可重入函数包括:rand, srand getenv, getenv_s strtokstrerrorasctime, ctime, localtime, gmtime setlocaleatomic_init tmpnammbrtoc16, c16rtomb, mbrtoc32, c32rtomb gethostbyaddrgethostbyname inet_ntoa建议1.3.2:字符串或指针作为函数参数时,请检查参数是否为NULL1. int Foo(int *p, int count)2. 3.if (p != NULL && count > 0) 4.int c = p0;5.6.7. 8.9. int Foo2()10. 11.int *arr = .12.int count = .13.Foo(arr, count);14.15. 如果字符串或者指针作为函数参数,为了防止空指针引用错误,在引用前必须确保该参数不为NULL,如果上层调用者已经保证了该参数不可能为NULL,在调用本函数时,在函数开始处可以加ASSERT进行校验。 例如下面的代码,因为BYTE *p有可能为NULL,因此在使用前需要进行判断。下面的代码,由于p的合法性由调用者保证,对于Foo函数,不可能出现p为NULL的情况,因此加上ASSERT进行校验。1.2.3.4.5.6.7.8.9.int Foo(int *p, int count)ASSERT(p != NULL); /ASSERT is added to verify p. ASSERT(count > 0);int c = p0;.int Foo2()10. 11. int *arr = .12. int count = .13. .14. if (arr != NULL && count > 0) 15. Foo(arr, count);16.17. .18. 建议1.3.3:在函数的开始处对参数进行ASSERT操作(API除外)ASSERT用于检测代码设计上的错误,如果ASSERT被触发,说明代码的设计不符合编码人员的预期。 在函数的开始处,对参数进行必要的ASSERT操作,可以在测试阶段有效地检验编码人员对代码设计上的预期。1.4 循环规则1.4.1:循环必须有退出条件循环如果没有退出条件,那么程序无法安全退出。 以下代码,在一个大循环内接收外部数据并进行处理,但没有退出条件,会导致该程序无法正常退出。4.if(msg != NULL) 5.ParseMsg(msg, size);6.FreeMsg(msg);7.8. 1. while (TRUE) 2. int size = 0;3. unsigned char *msg = ReceiveMsg(&size);例外: 1、操作系统软件的IDLE线程,可能需要无限循环 2、操作系统在不可恢复的错误中,为避免更多错误发生,进入指令无限循环。例如:1.2.3.4.5.6.7.8.void Reboot(void)reboot(reboot_cmd);while (1) CoreWait();3、嵌入式设备的操作系统或主流程,可能使用无限循环。例如:1. void OsTask()2. 3. .4. while (1)5. 6. msgHdl = RECEIVE(OS_WAIT_FOREVER, &msgId, &senderPid);7. if (msgHdl = 0)8. 9. continue;10.11. switch (msgId)12. 13. .14.15.16.17. (void)FREE(msgHdl);相关指南:MISRA.2004.Rule 13.5 (required):

    注意事项

    本文(华为C&amp;amp;C语言安全编程规范_V3.1.docx)为本站会员(暗伤)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开