MISRA代码审查这项工作要怎样去开展,以及审查中发现问题之后要怎样形成闭环,这件事情不能简单地等同于运行一次静态分析工具,再把告警数量降到零。MISRA的合规检查,既包含可以由工具自动识别的编码规则,也包含那些需要结合设计文档和人工判断才能完成的指令要求。一套相对完整的审查过程,应当先把适用的版本、代码覆盖范围和规则等级确定下来,再把工具检查、人工评审、问题修复、偏离审批和回归验证这几项工作串联在一起。如果不是这样,就算工具报告已经显示全部处理完毕,项目仍然可能缺少可以追溯的合规证据。
一、MISRA代码审查怎么开展
代码审查正式开始之前,需要先把审查的标准口径固定下来。不同的项目可能采用不同版本的MISRA,修订内容和规则重分类的方式也可能不一样,各种工具能够支持的检查范围也不完全相同。如果同一批代码由不同的人员使用不同的配置去检查,那么检查出来的告警数量和严重程度就很难放在一起进行比较。
1、确定审查范围和规则基线
首先需要明确,本次审查覆盖的范围是手写的代码、自动生成的代码、第三方的代码,还是整个软件系统。同时还要记录清楚所采用的语言版本、编译器、目标平台以及MISRA规则的版本。对于Mandatory、Required和Advisory这几类规则,还需要说明项目是否对它们进行了更严格的重新分类。Mandatory规则一旦出现违反的情况,就不能据此声明代码符合相应的MISRA要求;Required规则如果确实无法修正,就需要进入正式的偏离流程。
2、建立规则执行计划
在【规则执行计划】当中,需要记录清楚每一条规则是由静态分析工具来负责检查,还是依靠编译器来检查,又或者是由人工来负责评审。
静态分析工具并不能够完整地覆盖所有的规则和指令,特别是那些涉及到系统整体范围、设计约束条件,以及过程文档的内容。执行计划当中还应当保存好工具版本、配置文件、调用选项以及检测能力的证明材料,这样做是为了避免在后续升级了工具或者调整了参数之后,检查结果的口径发生了变化,却没有留下任何记录。
3、结合工具结果开展人工复核
工具产生的告警信息,不能直接等同于真实的规则违反。每一条消息都需要经过判断,看它是真实的违规、存在违规的可能、属于工具的误报,还是虽然不违反MISRA但仍然值得关注的代码写法。对于那些跨文件的函数调用、未经初始化的数据、指针在不同函数之间的传递、宏展开之后的结果,以及由实现定义的行为,不能只盯着告警所在的那一行代码,还需要把调用关系、类型定义和编译环境放在一起综合审查。MISRA合规过程本身也要求,要对工具产生的消息进行调查,并且保留下相应的判断记录。
二、MISRA代码审查发现问题后怎么处理
发现问题以后,应当优先选择去修改代码,而不是先想办法把告警压制下去。修改代码可以消除风险,也可以减少在后续版本中反复解释的成本。只有确实受到硬件寄存器、第三方接口、性能约束或者既有架构限制的情况下,才去考虑使用偏离这种方式。
1、先判断问题真实性和影响范围
重新复核规则的含义、代码的上下文以及工具的配置,确认这个问题到底是不是真实存在的。对于确认真实的违规,还要继续看它是仅仅影响当前这一条语句,还是在多个文件、宏定义或者公共接口当中重复出现。对于那些由同一个根本原因产生出来的大量告警,应当先修复公共的类型、接口或者宏定义,而不是逐条去做表面上的修改。
2、制定修复方案并检查副作用
修复MISRA问题不能只追求让告警消息消失。类型转换、控制流结构的重构、指针处理方式的改变,还有将表达式进行拆分,这些改动都有可能改变程序最终的运行结果、执行时间或者内存的占用情况。修改之前需要先确认清楚原来的设计意图,修改之后还要重新编译,并且执行单元测试、静态分析,以及必要的在目标环境下的测试,防止出现合规问题解决了,却把功能或者时序方面的新问题带了进来。
3、无法修复时建立偏离记录
在【偏离记录】当中,需要写明所违反的规则、适用的代码位置、无法修改的原因、风险等级的评估、施加的限制条件,以及采取了哪些补偿措施。
偏离的理由不能只写“工具误报”或者“历史代码不修改”这样简单。每一个偏离的实例,都应当能够定位到具体的文件、具体的代码位置,或者某一种受控的使用场景,并且要由具备相应技术能力的人员来进行评审和批准。如果有多处位置属于同一种受控的场景,可以使用统一的偏离依据,但仍然需要保留实际应用到了哪些位置的清单。
三、MISRA代码问题怎么完成闭环
问题被修复或者偏离的申请获得批准之后,还需要证明当前的版本已经重新接受过检查,而且处理的结果能够被后续进行审计的人员看明白。仅仅在工具的操作界面里面,把状态从“打开”改成“已处理”,通常还不足以构成一个完整的闭环。
1、建立问题追踪关系
按照【问题记录】→【修复提交】→【复查结果】→【关闭证据】这样的顺序,将追溯关系建立起来。
问题的记录应当包含规则的编号、文件所在的位置、问题的分类、责任人的姓名,以及计划在什么时间完成。修复之后,要把代码的提交记录和评审通过的记录关联到这个问题上面,然后再保存好重新扫描之后的结果。对于那些走了偏离流程的问题,则要关联上偏离的编号、审批人和适用的版本范围,防止代码发生变化以后,还在继续沿用那些已经失去了效力的偏离结论。
2、执行回归审查
重新运行一遍与基线配置保持一致的分析工具,确认原来报告的问题确实已经不再出现,同时还要检查有没有新产生的告警,以及那些被本次修改所影响到的文件。当公共的头文件、类型定义或者宏定义发生了变化的时候,需要把回归审查的范围进一步扩大,因为一次修改有可能同时改变多个编译单元的分析结果。对于系统级别的规则,还需要做整个程序范围内的分析,不能只单独扫描本次修改过的那些文件。
3、形成合规结论
一个项目阶段结束的时候,应当把规则的执行计划、工具的配置情况、还没有关闭的问题清单、已经批准的偏离记录,以及审查的最终结论汇总在一起。审查的结论当中,不能只写一个告警的总数,而是需要说明有哪些规则是已经被工具所覆盖到的,有哪些规则是经过了人工检查的,当前还存在哪些经过批准的偏离,以及是不是还有那些会阻碍做出合规声明的问题。按照这种方式形成的结论,才能够支撑版本的对外发布、应对客户的审查,以及后续发生变更时的追溯。
总结
MISRA代码审查怎么开展,以及MISRA审查发现问题后怎么闭环,其中的关键在于,先把一套统一的规则基线和执行计划建立起来,然后再把工具的自动扫描和人工的逐项复核结合在一起。发现了真实的违规之后,应当优先去修改代码,并且对功能、时序和回归的结果进行验证;对于那些确实没有办法修改的内容,就要通过受控的偏离记录,把原因和风险都说明清楚。在最后,还需要把问题的记录、代码的提交、复查的结果和关闭的证据全部关联在一起,确保每一项处理的过程都可以追溯,到了这一步,MISRA的审查工作才算真正完成了闭环。