☰
  • 项目介绍
  • 规则目录
  • 附录
search
•••

360 安全规则集合 version-1.4.0

Bjarne Stroustrup: “C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off.”
logo

针对 C 和 C++ 语言,本文收录了 532 种需要重点关注的问题, 每个问题对应一条规则,可作为代码审计依据或编程规范条款,也可为相关培训提供指导意见。

本文是适用于不同应用场景的规则集合,读者可从中选取某个子集以适应自身需求。

规则分类

本文以 ISO/IEC 9899:2011、ISO/IEC 14882:2011 为依据,兼顾 C++17 及历史标准,将规则分为:

  1. Security:敏感信息防护与安全策略
  2. Resource:资源管理
  3. Precompile:预处理、宏、注释、文件
  4. Global:全局及命名空间作用域
  5. Type:类型设计与实现
  6. Declaration:声明
  7. Exception:异常
  8. Function:函数实现
  9. Control:流程控制
  10. Expression:表达式
  11. Literal:字面常量
  12. Cast:类型转换
  13. Buffer:缓冲区
  14. Pointer:指针
  15. Interruption:中断与信号处理
  16. Concurrency:异步与并发
  17. Style:样式与风格

规则组成

  • 标识:规则的唯一标识,以“ID_”开头
  • 标题:规则的定义和简要说明
  • 说明:规则设立的原因、违反规则的后果
  • 示例:例举符合规则(Compliant)的和违反规则(Non-compliant)的代码
  • 相关:与当前规则有相关性的规则,可作为扩展阅读的线索
  • 依据:规则依照的 ISO/IEC 标准条目
  • 配置:某些规则的细节可灵活设置,审计工具可以此为参照实现定制化功能
  • 参考:规则参考的其他规范条目,如 C++ Core Guidelines、MISRA、SEI CERT Coding Standards 等

其中“依据”以“标准名称:版本 章节编号(段落编号)-性质”的格式引用标准,“性质”一项分为:

  • undefined:可使程序产生未定义的行为,其后果是不可预期的
  • unspecified:可使程序产生未声明的行为,具体行为由编译器或环境定义,没有明确的文档
  • implementation:可使程序产生由实现定义的行为,具体行为由编译器或环境定义,具有明确的文档,但不具备可移植性
  • deprecated:已被废弃的或不建议继续使用的编程方式

没有特殊说明的规则同时适用于 C 语言和 C++ 语言,只适用于某一种语言的规则会有相关说明。

规则目录

  1. Security
    1. 敏感数据不可写入代码
    2. 敏感数据不可被系统外界感知
    3. 敏感数据在使用后应被有效清理
    4. 公共成员或全局对象不应记录敏感数据
    5. 与内存空间布局相关的信息不可被外界感知
    6. 与网络地址相关的信息不应写入代码
    7. 预判用户输入造成的不良后果
    8. 对资源设定合理的访问权限
    9. 对用户落实有效的权限管理
    10. 避免引用危险符号名称
    11. 避免使用危险接口
    12. 避免使用已过时的接口
    13. 避免除 0 等计算异常
    14. 选择安全的异常处理方式
    15. 不应产生或依赖未定义的行为
    16. 不应依赖未声明的行为
    17. 避免依赖由实现定义的行为
    18. 保证组件的可靠性
    19. 保证第三方软件的可靠性
    20. 隔离非正式功能的代码
    21. 启用平台和编译器提供的防御机制
    22. 禁用不安全的编译选项
  2. Resource
    1. 避免资源泄露
    2. 避免内存泄露
    3. 不可访问未初始化或已释放的资源
    4. 使资源接受对象化管理
    5. 资源的分配与回收方法应成对提供
    6. 资源的分配与回收方法应配套使用
    7. 不应在模块之间传递容器类对象
    8. 不应在模块之间传递非标准布局类型的对象
    9. 对象申请的资源应在析构函数中释放
    10. 对象被移动后应重置状态再使用
    11. 构造函数抛出异常需避免相关资源泄漏
    12. 不可重复释放资源
    13. 用 delete 释放对象需保证其类型完整
    14. 用 delete 释放对象不可多写中括号
    15. 用 delete 释放数组不可漏写中括号
    16. 不可释放非动态分配的内存
    17. 在一个表达式语句中最多使用一次 new
    18. 流式资源对象不应被复制
    19. 避免使用变长数组
    20. 避免使用在栈上动态分配内存的函数
    21. 非动态分配的数组不应过大
    22. 避免不必要的内存分配
    23. 避免分配大小为零的内存空间
    24. 避免动态内存分配
    25. 判断资源分配函数的返回值是否有效
    26. 在 C++ 代码中禁用 C 资源管理函数
  3. Precompile
    1. Include
      1. include 指令应符合标准格式
      2. 避免在 include 指令中使用特殊字符
      3. 避免在 include 指令中使用反斜杠
      4. 避免在 include 指令中使用绝对路径
      5. include 指令应位于文件的起始部分
      6. 禁用具有不良影响的头文件
      7. 避免在 C++ 代码中包含 C 头文件
      8. 源文件不应被包含
    2. Macro-definition
      1. 宏应遵循合理的命名方式
      2. 不可定义具有保留意义的宏名称
      3. 不可取消定义具有保留意义的宏名称
      4. 宏定义为表达式时应该用括号括起来
      5. 表达式中的宏参数应该用括号括起来
      6. 由多个语句组成的宏定义应该用 do-while(0) 括起来
      7. 宏定义中的 # 和 ## 运算符不应嵌套使用
      8. 不应使用宏定义常量
      9. 不应使用宏定义类型
      10. 可由函数实现的功能不应使用宏实现
      11. 宏不应被重定义
      12. 只应在全局作用域中定义宏
      13. 避免宏被取消定义
    3. Macro-usage
      1. 宏的实参不应有副作用
      2. 宏的实参个数不可小于形参个数
      3. 宏的实参个数不可大于形参个数
      4. va_start 或 va_copy 应配合 va_end 使用
      5. va_arg 的类型参数应符合要求
      6. 在 C++ 代码中不应使用宏 offsetof
    4. Directive
      1. 头文件不应缺少守卫
      2. 不应出现非标准格式的预编译指令
      3. 不应使用非标准预编译指令
      4. 避免使用 pragma 指令
      5. 在非自动生成的代码中不应使用 line 指令
      6. 在宏的参数列表中不应使用预编译指令
      7. 相互关联的条件编译指令应在同一文件中
      8. 条件编译指令控制表达式的值应为 0 或 1
      9. 对编译警告的屏蔽应慎重
      10. 在高级别的警告设置下编译
    5. Comment
      1. 注释不可嵌套
      2. 注释应出现在合理的位置
      3. 关注 TODO、FIXME、XXX、BUG 等特殊注释
      4. 单行注释不应以反斜杠结尾
    6. File
      1. 源文件扩展名应一致
      2. 头文件扩展名应一致
      3. 非空源文件应以换行符结尾
      4. 源代码文件的行数不应过多
    7. Other
      1. 避免出现 trigraph sequences
      2. 禁用 digraphs
      3. 除转义字符、宏定义之外不应使用反斜杠
  4. Global
    1. 全局名称应遵循合理的命名方式
    2. 为代码设定合理的命名空间
    3. main 函数只应位于全局作用域中
    4. 不应在头文件中使用 using 指令
    5. 不应在头文件中使用静态声明
    6. 不应在头文件中定义匿名命名空间
    7. 不应在头文件中实现函数或定义对象
    8. 不应在匿名命名空间中使用静态声明
    9. 全局对象的初始化不可依赖未初始化的对象
    10. 全局对象只应为常量或静态对象
    11. 全局对象只应为常量
    12. 全局对象不应同时被 static 和 const 等关键字限定
    13. 全局及命名空间作用域中禁用 using 指令
    14. 避免无效的 using 指令
    15. 不应定义全局 inline 命名空间
    16. 不可修改 std 命名空间
  5. Type
    1. Class
      1. 类的非常量数据成员均应为 private
      2. 类的非常量数据成员不应为 protected
      3. 类不应既有 public 数据成员又有 private 数据成员
      4. 有虚函数的基类应具有虚析构函数
      5. 避免多重继承自同一非虚基类
      6. 存在析构函数或拷贝赋值运算符时,不应缺少拷贝构造函数
      7. 存在拷贝构造函数或析构函数时,不应缺少拷贝赋值运算符
      8. 存在拷贝构造函数或拷贝赋值运算符时,不应缺少析构函数
      9. 存在任一拷贝、移动、析构相关的函数时,应定义所有相关函数
      10. 避免重复实现由默认拷贝、移动、析构函数完成的功能
      11. 可接受一个参数的构造函数需用 explicit 关键字限定
      12. 重载的类型转换运算符需用 explicit 关键字限定
      13. 不应过度使用 explicit 关键字
      14. 带模板的赋值运算符不应与拷贝或移动赋值运算符混淆
      15. 带模板的构造函数不应与拷贝或移动构造函数混淆
      16. 抽象类禁用拷贝和移动赋值运算符
      17. 数据成员的数量应在规定范围之内
      18. 数据成员之间的填充数据不应被忽视
      19. 常量成员函数不应返回数据成员的非常量指针或引用
      20. 类成员应按 public、protected、private 的顺序声明
      21. POD 类和非 POD 类应分别使用 struct 和 class 关键字定义
      22. 继承层次不应过深
    2. Enum
      1. 同类枚举项的值不应相同
      2. 合理初始化各枚举项
      3. 不应使用匿名枚举声明
      4. 用 enum class 取代 enum
    3. Union
      1. 联合体内禁用非基本类型的对象
      2. 禁用在类之外定义的联合体
      3. 禁用联合体
  6. Declaration
    1. Naming
      1. 遵循合理的命名方式
      2. 不应定义具有保留意义的名称
      3. 局部名称不应被覆盖
      4. 成员名称不应被覆盖
      5. 全局名称不应被覆盖
      6. 类型名称不应重复定义
      7. 类型名称不应与对象或函数名称相同
      8. 不应存在拼写错误
    2. Qualifier
      1. const、volatile 不应重复
      2. const、volatile 限定指针类型的别名是可疑的
      3. const、volatile 不可限定引用
      4. const、volatile 限定类型时的位置应统一
      5. const、volatile 等关键字不应出现在基本类型名称的中间
      6. 指向常量字符串的指针应使用 const 声明
      7. 声明枚举类型的底层类型时不应使用 const 或 volatile
      8. 对常量的定义不应为引用
      9. 禁用 restrict 指针
      10. 非适当场景禁用 volatile 关键字
      11. 相关对象未被修改时应使用 const 声明
    3. Specifier
      1. 合理使用 auto 关键字
      2. 不应使用已过时的关键字
      3. 不应使用多余的 inline 关键字
      4. extern 关键字不应作用于类成员的声明或定义
      5. 重写的虚函数应声明为 override 或 final
      6. override 和 final 关键字不应同时出现在声明中
      7. override 或 final 关键字不应与 virtual 关键字同时出现在声明中
      8. 不应将 union 设为 final
      9. 未访问 this 指针的成员函数应使用 static 声明
      10. 声明和定义内部链接的对象和函数时均应使用 static 关键字
      11. inline、virtual、static、typedef 等关键字的位置应统一
    4. Declarator
      1. 用 auto 声明指针或引用时应显式标明 *、& 等符号
      2. 禁用可变参数列表
      3. 禁用柔性数组
      4. 接口的参数类型和返回类型不应为 void*
      5. 类成员的类型不应为 void*
      6. 数组大小应被显式声明
      7. 不应将类型定义和对象声明写在一个语句中
      8. 不应将不同类别的声明写在一个语句中
      9. 在 C++ 代码中用容器代替 C 数组
    5. Parameter
      1. 函数原型声明中的参数应具有合理的名称
      2. 不应将数组作为函数的形式参数
      3. parmN 的声明应符合要求
      4. 虚函数参数的默认值应与基类中声明的一致
      5. 不建议虚函数的参数有默认值
      6. C 代码中参数列表如果为空应声明为“(void)”
      7. C++ 代码中参数列表如果为空不应声明为“(void)”
      8. 声明数组参数的大小时禁用 static 关键字
    6. Initializer
      1. 用列表初始化代替用等号或小括号的方式进行初始化
      2. 在初始化列表中对聚合体也应使用初始化列表
      3. 初始化列表中不应存在重复的指派符
    7. Object
      1. 不应产生无效的临时对象
      2. 对象初始化不可依赖自身的值
      3. 字节的类型应为 std::byte 或 unsigned char
    8. Function
      1. 派生类不应重新定义与基类相同的非虚函数
      2. 重载运算符的返回类型应与内置运算符相符
      3. 赋值运算符应返回所属类的非 const 左值引用
      4. 拷贝构造函数的参数应为同类对象的 const 左值引用
      5. 拷贝赋值运算符的参数应为同类对象的 const 左值引用
      6. 移动构造函数的参数应为同类对象的非 const 右值引用
      7. 移动赋值运算符的参数应为同类对象的非 const 右值引用
      8. 不应重载取地址运算符
      9. 不应重载逗号运算符
      10. 不应重载“逻辑与”和“逻辑或”运算符
      11. 拷贝和移动赋值运算符不应为虚函数
      12. 比较运算符不应为虚函数
      13. 在 final 类中不应声明虚函数
    9. Bitfield
      1. 对位域声明合理的类型
      2. 位域长度不应超过类型长度
      3. 有符号整型对象的位域长度不应为 1
      4. 不应对枚举对象声明位域
      5. 禁用位域
    10. Complexity
      1. 不应采用复杂的声明
      2. 声明中不应包含过多的指针嵌套
      3. 在一个语句中不应声明多个对象或函数
    11. Old-style
      1. 避免隐式声明
      2. 不应省略声明对象或函数的类型
      3. 弃用老式声明与定义
    12. Other
      1. 在合理的位置声明
      2. 声明与实现应一致
      3. 遵循 One Definition Rule
      4. 不应存在没有被用到的标签
      5. 不应存在没有被用到的静态声明
      6. 不应存在没有被用到的 private 成员
      7. 不应存在没有被用到的局部声明
      8. 使用便于移植的类型
      9. 避免使用已过时的标准库组件
      10. 不应使用具有 deprecated 属性的函数、对象或类型
  7. Exception
    1. 保证异常安全
    2. 处理所有异常
    3. 不应抛出过于宽泛的异常
    4. 不应捕获过于宽泛的异常
    5. 不应抛出非异常类型的对象
    6. 不应捕获非异常类型的对象
    7. 全局对象的初始化过程不可抛出异常
    8. 析构函数不可抛出异常
    9. 内存回收函数不可抛出异常
    10. 对象交换过程不可抛出异常
    11. 移动构造函数和移动赋值运算符不可抛出异常
    12. 异常类的拷贝构造函数不可抛出异常
    13. 异常类的构造函数和异常信息相关的函数不应抛出异常
    14. 与标准库相关的 hash 过程不应抛出异常
    15. 异常类的拷贝、移动构造函数和析构函数均应是可访问的
    16. 使用 noexcept 关键字标注不抛出异常的函数
    17. 由 noexcept 关键字标注的函数不可产生未处理的异常
    18. 避免异常类多重继承自同一非虚基类
    19. 通过引用捕获异常
    20. 捕获异常时不应产生对象切片问题
    21. 捕获异常后不应直接再次抛出异常
    22. 重新抛出异常时应使用空 throw 表达式(throw;)
    23. 不应在 catch 子句外使用空 throw 表达式(throw;)
    24. 不应抛出指针
    25. 不应抛出 NULL
    26. 不应抛出 nullptr
    27. 不应在模块之间传播异常
    28. 禁用动态异常说明
    29. 禁用 C++ 异常
  8. Function
    1. main 函数的返回类型只应为 int
    2. main 函数不应被调用、重载或被 inline、static 等关键字限定
    3. 参数名称在声明处和实现处应保持一致
    4. 多态类的对象作为参数时不应采用值传递的方式
    5. 不应存在未被使用的具名形式参数
    6. 形式参数不应被修改
    7. 复制成本高的参数不应按值传递
    8. 转发引用只应作为 std::forward 的参数
    9. 局部对象在使用前应被初始化
    10. 动态创建的对象在使用前应被初始化
    11. 成员须在声明处或构造时初始化
    12. 基类对象构造完毕之前不可调用成员函数
    13. 在面向构造或析构函数体的 catch 子句中不可访问非静态成员
    14. 成员初始化应遵循声明的顺序
    15. 在对象的构造函数中不应使用其动态类型
    16. 在对象的析构函数中不应使用其动态类型
    17. 避免在析构函数中调用 exit 函数
    18. 避免在拷贝构造函数中实现复制之外的功能
    19. 避免在移动构造函数中实现数据移动之外的功能
    20. 拷贝赋值运算符应处理参数是自身对象时的情况
    21. 不应存在无效的写入操作
    22. 不应存在没有副作用的语句
    23. 不应存在得不到执行机会的代码
    24. 有返回值的函数其所有分枝都应显式返回
    25. 不可返回局部对象的地址或引用
    26. 不可返回临时对象的地址或引用
    27. 不可引用失效的临时对象
    28. 合理设置 lambda 表达式的捕获方式
    29. 函数返回值不应为右值引用
    30. 函数返回值不应为常量对象
    31. 函数返回值不应为基本类型的常量
    32. 被返回的表达式应与函数的返回类型一致
    33. 被返回的表达式不应为相同的常量
    34. 具有 noreturn 属性的函数不应返回
    35. 具有 noreturn 属性的函数返回类型只应为 void
    36. 由 atexit、at_quick_exit 指定的处理函数应正常返回
    37. 函数模板不应被特化
    38. 函数的退出点数量应在规定范围之内
    39. 函数的标签数量应在规定范围之内
    40. 函数的行数应在规定范围之内
    41. lambda 表达式的行数应在规定范围之内
    42. 函数参数的数量应在规定范围之内
    43. 不应定义复杂的内联函数
    44. 避免函数调用自身
    45. 不可递归调用析构函数
    46. 作用域及类型嵌套不应过深
    47. 汇编代码不应与普通代码混合
    48. 避免重复的函数实现
  9. Control
    1. If
      1. if 语句不应被分号隔断
      2. if...else-if 分枝的条件不应重复
      3. if...else-if 分枝的条件不应被遮盖
      4. if 分枝和 else 分枝的代码不应完全相同
      5. 不应存在完全相同的 if...else-if 分枝
      6. if 分枝和隐含的 else 分枝不应完全相同
      7. 没有 else 子句的 if 语句与其后续代码相同是可疑的
      8. if 分枝和 else 分枝的起止语句不应相同
      9. if 语句作用域的范围不应有误
      10. 如果 if 关键字前面是右大括号,if 关键字应另起一行
      11. if 语句的条件不应为赋值表达式
      12. if 语句不应为空
      13. if...else-if 分枝数量应在规定范围之内
      14. if 分枝中的语句应该用大括号括起来
      15. 所有 if...else-if 分枝都应以 else 子句结束
    2. For
      1. for 语句不应被分号隔断
      2. for 语句中不应存在无条件的跳转语句
      3. for 语句作用域的范围不应有误
      4. for 语句没有明确的循环变量时应改用 while 语句
      5. for 循环体不应为空
      6. for 循环变量不应为浮点型
      7. for 循环变量不应在循环体内被改变
      8. for 循环变量应在循环条件范围内有效增减
      9. 嵌套的 for 语句不应使用相同的循环变量
      10. for 循环体应该用大括号括起来
    3. While
      1. while 语句不应被分号隔断
      2. while 语句中不应存在无条件的跳转语句
      3. while 语句的条件不应为赋值表达式
      4. while 语句作用域的范围不应有误
      5. while 循环体不应为空
      6. while 循环体应该用大括号括起来
    4. Do
      1. 不建议使用 do 语句
      2. do-while 循环体不应为空
      3. do-while 循环体应该用大括号括起来
      4. 注意 do-while(0) 中可疑的 continue 语句
    5. Switch
      1. switch 语句不应被分号隔断
      2. switch 语句不应为空
      3. case 标签的值不可超出 switch 条件表达式的取值范围
      4. switch 语句的子句均应从属于某个 case 或 default 分枝
      5. case 和 default 标签应直接从属于 switch 语句
      6. 不应存在紧邻 default 标签的空 case 标签
      7. 不应存在完全相同的 case 或 default 分枝
      8. switch 语句的条件表达式不应为 bool 型
      9. switch 语句不应只包含 default 标签
      10. switch 语句不应只包含一个 case 标签
      11. switch 语句分枝数量应在规定范围之内
      12. switch 语句应配有 default 分枝
      13. switch 语句的每个非空分枝都应该用无条件的 break 或 return 语句终止
      14. switch 语句应该用大括号括起来
      15. switch 语句不应嵌套
    6. Try-catch
      1. try 关键字的作用域不应为空
      2. catch 子句不应为空
      3. 不应嵌套 try-catch 语句
      4. 捕获所有异常的 catch(...) 子句应位于最后
      5. 面向派生类的 catch 子句应排在面向基类的 catch 子句之前
    7. Jump
      1. 禁止 goto 语句向嵌套的或无包含关系的作用域跳转
      2. 禁止 goto 语句向前跳转
      3. 禁用 goto 语句
      4. 禁用 setjmp、longjmp
      5. 不应存在不受条件控制的跳转语句
      6. 不应存在不改变程序流程的跳转语句
      7. 避免使用跳转语句退出循环
  10. Expression
    1. Logic
      1. 不应存在无意义的重复子表达式
      2. 逻辑子表达式之间不应存在矛盾
      3. 不应存在多余的逻辑子表达式
      4. 作为控制条件的逻辑表达式不应恒为真或恒为假
      5. 逻辑表达式及逻辑子表达式不应为常量
      6. 逻辑表达式的右子表达式不应有副作用
      7. 化简可被合并的逻辑子表达式
      8. 化简可转换为逻辑表达式的三元表达式
      9. 控制条件应为 bool 型表达式
      10. !、&&、|| 的子表达式应为 bool 型表达式
      11. &&、|| 的子表达式应为后缀表达式
    2. Evaluation
      1. 不可依赖不会生效的副作用
      2. 不可依赖未声明的求值顺序
      3. 在表达式中不应多次读写同一对象
      4. bool 对象不应参与位运算、大小比较、数值增减
      5. 枚举对象不应参与位运算或算数运算
      6. 参与数值运算的 char 对象应显式声明 signed 或 unsigned
      7. signed char 和 unsigned char 对象只应用于数值计算
      8. 不应将 NULL 当作整数使用
      9. 运算结果不应溢出
      10. 移位数量不应超过相关类型比特位的数量
      11. 按位取反需避免由类型提升产生的多余数据
      12. 逗号表达式的子表达式应具有必要的副作用
      13. 自增、自减表达式不应作为子表达式
    3. Operator
      1. 注意运算符优先级,避免非预期的结果
      2. 负号不应作用于无符号整数
      3. 位运算符不应作用于有符号整数
      4. 赋值运算符左右子表达式不应相同
      5. 除法和求余运算符左右子表达式不应相同
      6. 减法运算符左右子表达式不应相同
      7. 异或运算符左右子表达式不应相同
      8. &=、|=、^=、-=、/=、%= 左右子表达式不应相同
      9. 比较运算符左右子表达式不应相同
      10. 不应重复使用一元运算符
    4. Assignment
      1. 不可将对象的值赋给具有部分重叠区域的另一个对象
      2. 不应出现复合赋值的错误形式
      3. 避免出现复合赋值的可疑形式
      4. 注意赋值运算符与一元运算符的空格方式
      5. 赋值表达式不应作为子表达式
    5. Comparison
      1. 参与比较的对象之间应具备合理的大小关系
      2. 不应使用 == 或 != 判断浮点数是否相等
      3. 指针不应与字符串常量直接比较
      4. 有符号数不应和无符号数比较
      5. 不应比较非同类枚举值
      6. 比较运算不可作为另一个比较运算的直接子表达式
    6. Call
      1. 不应忽略重要的返回值
      2. 不可臆断返回值的意义
      3. 避免对象切片
      4. 避免显式调用析构函数
      5. 不应将非 POD 对象传入可变参数列表
      6. C 格式化字符串需要的参数个数与实际传入的参数个数应一致
      7. C 格式化占位符与其对应参数的类型应一致
      8. C 格式化字符串应为常量
      9. 在 C++ 代码中禁用 C 字符串格式化方法
      10. 形参与实参均为数组时,数组大小应一致
      11. 禁用不安全的字符串函数
      12. 禁用 atof、atoi、atol 以及 atoll 等函数
      13. 合理使用 std::move
      14. 合理使用 std::forward
    7. Sizeof
      1. sizeof 不应作用于数组参数
      2. sizeof 不应作用于比较或逻辑表达式
      3. sizeof 作用于指针是可疑的
      4. 被除数不应是作用于指针的 sizeof 表达式
      5. 指针加减偏移量时计入 sizeof 是可疑的
      6. sizeof 表达式的结果不应与 0 或负数比较
      7. sizeof 不应再作用于 sizeof 表达式
      8. C++ 代码中 sizeof 不应作用于 NULL
      9. sizeof 不可作用于 void
    8. Assertion
      1. 断言中的表达式不应恒为真
      2. 断言中的表达式不应有副作用
      3. 断言中的表达式不应过于复杂
    9. Complexity
      1. 表达式不应过于复杂
    10. Other
      1. 不应访问填充数据
      2. new 表达式只可用于赋值或当作参数
      3. 数组下标应为整型表达式
      4. 禁用逗号表达式
  11. Literal
    1. 转义字符的反斜杠不可误写成斜杠
    2. 在字符常量中用转义字符表示制表符和控制字符
    3. 在字符串常量中用转义字符表示制表符和控制字符
    4. 8 进制或 16 进制转义字符不应与其他字符连在一起
    5. 不应使用非标准转义字符
    6. 不应连接不同前缀的字符串常量
    7. 字符串常量中不应存在拼写错误
    8. 常量后缀由应由大写字母组成
    9. 无符号整数常量应具有后缀 U
    10. 不应使用非标准常量后缀
    11. 禁用 8 进制常量
    12. 小心遗漏逗号导致的非预期字符串连接
    13. 不应存在 magic number
    14. 不应存在 magic string
    15. 不应使用多字符常量
    16. 合理使用数字分隔符
  12. Cast
    1. 避免类型转换造成数据丢失
    2. 避免数据丢失造成类型转换失效
    3. 避免有符号整型与无符号整型相互转换
    4. 不应将负数转为无符号数
    5. 避免与 void* 相互转换
    6. 避免向下类型转换
    7. 指针与整数不应相互转换
    8. 类型转换不应去掉 const、volatile 等属性
    9. 不应转换无继承关系的指针或引用
    10. 不应转换无 public 继承关系的指针或引用
    11. 非 POD 类型的指针与基本类型的指针不应相互转换
    12. 不同的字符串类型之间不可直接转换
    13. 避免向对齐要求更严格的指针转换
    14. 避免转换指向数组的指针
    15. 避免转换函数指针
    16. 向下动态类型转换应使用 dynamic_cast
    17. 判断 dynamic_cast 转换是否成功
    18. 不应转换 new 表达式的类型
    19. 不应存在多余的类型转换
    20. 可用其他方式完成的转换不应使用 reinterpret_cast
    21. 合理使用 reinterpret_cast
    22. 在 C++ 代码中禁用 C 风格类型转换
  13. Buffer
    1. 避免缓冲区溢出
    2. 为缓冲区分配足够的空间
    3. 确保字符串以空字符结尾
    4. memset 等函数不应作用于非 POD 对象
    5. memset 等函数长度相关的参数不应有误
    6. memset 等函数填充值相关的参数不应有误
  14. Pointer
    1. 避免空指针解引用
    2. 注意逻辑表达式内的空指针解引用
    3. 不可解引用未初始化的指针
    4. 不可解引用已失效的指针
    5. 避免指针运算的结果溢出
    6. 未指向同一数组的指针不可相减
    7. 未指向同一数组或同一对象的指针不可比较大小
    8. 未指向数组元素的指针不应与整数加减
    9. 避免无效的空指针检查
    10. 不应重复检查指针是否为空
    11. 不应使用非零常量对指针赋值
    12. 不应使用常量 0 表示空指针
    13. 在 C++ 代码中 NULL 和 nullptr 不应混用
    14. 在 C++ 代码中用 nullptr 代替 NULL
    15. 不应使用 false 对指针赋值
    16. 不应使用 '\0' 等字符常量对指针赋值
    17. 指针不应与 false 比较大小
    18. 指针不应与 '\0' 等字符常量比较大小
    19. 指针与空指针不应比较大小
    20. 不应判断 this 指针是否为空
    21. 禁用 delete this
    22. 释放指针后应将指针赋值为空或其他有效值
    23. 函数取地址时应显式使用 & 运算符
    24. 指针与整数的加减运算应使用数组下标的方式
  15. Interruption
    1. 避免异步信号处理产生的数据竞争
    2. 避免在异步信号处理函数中使用非异步信号安全函数
    3. SIGFPE、SIGILL、SIGSEGV 等信号的处理函数不可返回
    4. 禁用 signal 函数
    5. 信号处理函数应为 POF
  16. Concurrency
    1. 访问共享数据应遵循合理的同步机制
    2. 避免在事务中通过路径多次访问同一文件
    3. 避免在事务中多次非同步地访问原子对象
    4. 避免死锁
    5. 避免异步终止线程
    6. 避免异步终止共享对象的生命周期
    7. 避免虚假唤醒造成同步错误
    8. 避免并发访问位域造成的数据竞争
    9. 在多线程环境中不可使用 signal 函数
  17. Style
    1. 遵循统一的代码编写风格
    2. 遵循统一的命名风格
    3. 遵循统一的空格风格
    4. 遵循统一的大括号风格
    5. 遵循统一的缩进风格
    6. 避免多余的括号
    7. 避免多余的分号

附录

  • C 未定义行为成因列表
  • C++ 未定义行为成因列表
Copyright©2024 360 Security Technology Inc., Licensed under the Apache-2.0 license.