在做 C/C++test 静态分析时,很多团队都会遇到 C/C++ test抑制规则怎么添加,C/C++ test抑制规则复扫后为什么还提示 这类问题。抑制规则不是简单把告警“隐藏掉”,它更像是一条确认记录:这条告警已经被判断过,当前场景下可以接受,后续报告里不再反复打扰开发人员。C/C++test 支持在源码、抑制文件和界面中处理指定 findings;如果是整条规则都不想检查,应该在测试配置里关闭规则,而不是给每个告警加抑制。
一、C/C++test抑制规则的添加方法
开发人员在利用C/C++test进行代码静态分析时,经常会碰到抑制规则不知道怎么加,或者加完重新扫描却依然报错的情况。抑制规则的本质并不是把报错信息直接藏起来,它其实更像是一个处理记录,用来证明这条报错已经被人工看过了,在目前的写代码场景下是可以被接受的,这样以后的检查报告里就不会总弹出提示。如果要把特定的告警在代码、文件或者软件界面里弄掉,C/C++test是支持这种操作的;不过,要是某些检测规则整个项目都不想用,那么开发人员应该去测试设置里把整条规则关掉,而不是对着每一个报错去加抑制。
1、在代码这一行的末尾加上抑制注释
如果开发人员只是想对某一行代码不作处理,那就可以在这行代码后面写上parasoft-suppress这一串字,这种做法能让人一眼看明白,以后大家一起看代码的时候也容易懂。
value = a | b; // parasoft-suppress CERT_C "hardware register bit operation"
这个parasoft-suppress是被用来把当前行的某条规则、某类规则或者所有规则给压下去的,在写这个语法的时候,具体的规则名字、类别或者代表全部的ALL都可以往上写,而且后边最好把不处理的原因也顺便写一下。在官方的资料里,关于单行抑制、规则大类抑制、好几条规则一起抑制,还有全部抑制的写法语气,都有给出具体的示例。
2、把注释写在下一行或者把代码块包起来
有时候报错的那行代码写得太长了,或者因为别的原因不方便把注释塞到行尾,开发人员就可以把注释放到下一行去。
3、利用parasoft.suppress这个文件来进行统一管辖
如果不希望把原本的代码改得乱七八糟,或者项目组规定了所有的抑制操作都要单独拿出来过目,那么把这些记录写进parasoft.suppress文件里是一个好办法。这个文件可以塞在跟报错代码同级的地方,也可以通过suppression.infile.location这个配置来指定一个固定的存放地方;相关资料也建议把这个抑制文件放到版本管理仓库里,这样大家都能用得到,分支合并的时候也方便检查。
二、为什么重新扫描之后原先的报错还在提示
在重新跑了扫描之后,要是发现原先的报错还在,这倒不一定是工具出了毛病没认出来,很多时候,是因为开发人员写的抑制条件和新扫出来的结果之间没有对上。工具在判断抑制的时候,不是只要看到有一条记录就行了,它会去核对文件名字、规则名字、行号是多少、报错长什么样、路径能不能对得齐。
1、规则的名字写错了,或者限制得太死
很多报错在表面上看起来差不多是一类事情,但由于它们的具体规则编号不一样,比如开发人员写的是抑制CERT_C-EXP45,但是重新扫描之后弹出来的,却是另外一个意思差不多但是换了名字的规则,或者它是别套规则里的编号,那之前写的抑制就不会自己跑去生效。
2、写抑制的位置和真正报错的那一行错开了
写在行尾的注释只能管这一行,写在下一行的只能管下面那一行,用大括号一样的东西圈起来的代码块也只能管中间那一段。一旦代码被格式化了、或者中间被塞了空行、又或者是宏展开的地方变了,那原本看着没问题的注释就会对不上位置。
3、抑制文件没有被现在的扫描环境加载进去
有时候开发人员在自己的电脑界面上看不见报错了,可是把代码传到服务器、或者用命令行跑流水线重新扫描的时候,报错又冒了出来,这往往是因为CI环境根本就没有读到parasoft.suppress这个文件。常见的情况有:文件忘记提交了、路径写成了自己电脑上的绝对路径、本地配置里写了suppression.infile.location但服务器的配置里没写。
三、抑制规则的排查与日常管理办法
代码里的抑制规则并不是写得越多越好,一个合格的抑制操作,应该能够讲清楚“为什么不解决这个问题”,而且在代码改动了之后,它还能被拿来重新检查。特别是在过MISRA、CERT或者是汽车行业的ISO 26262这种安全标准的时候,这些抑制的记录常常也是要交上去当评审材料的。
1、要先弄清楚到底是该改代码,还是该加抑制
遇到finding后,先看它是不是确实违反项目规范。如果代码能改,优先改代码。只有以下几类情况才更适合抑制:
1、工具误报,代码逻辑已经确认没有问题。
2、硬件寄存器、编译器扩展、平台接口导致规则不适用。
3、第三方代码或自动生成代码,不属于当前团队维护范围。
4、遗留接口暂时无法修改,但已经有评审记录和风险说明。
如果整条规则和项目完全不匹配,就不要给每个finding加抑制,而是在测试配置中关闭这条规则。抑制适合处理“个别例外”,关闭规则适合处理“整体不检查”。
2、原因不要写得太应付
在写reason的时候,不要只敷衍地写上ok、ignore或者是approved。这些词写了跟没写一样,以后大家审查的时候看不懂,也解释不清楚为什么这个报错能留着。比较稳妥的写法是把具体的场景和范围描述一下,比如:
reason: hardware register bit operation, reviewed in driver coding guideline
或者写成:
reason: generated protocol code, source is regenerated from approved model
如果是为了应付MISRA合规的流程,C/C++test允许在原因的开头写上false positive,这样属于误报的错误就不会被统计到DTP系统的MISRA Compliance报表里面去,不过这种写法要严格跟着团队的规矩来,不能自己瞎写。
3、重新扫描还有报错时的逐项核对顺序
复扫仍提示时,可以按下面顺序查:
1、确认当前finding的rule id是否和抑制里写的一致。
2、确认源码里的抑制注释是否在正确行、正确代码块。
3、确认parasoft.suppress文件是否被提交、被扫描环境读取。
4、确认文件路径是否因为工作区、分支、构建目录变化而不匹配。
5、确认测试配置是否换了,规则集是否多了等价规则或新规则。
6、确认是否用了line或message,而代码行号、告警文本已经变化。
如果是Qt宏、生成宏、平台宏这类很难逐条抑制的场景,也可以考虑基于正则表达式做行级自动抑制。C/C++test支持通过cpptest.result.line.suppressions.enabled和cpptest.result.line.suppressions.pattern配置对匹配行的违规进行抑制。
总结
总的来看,C/C++test抑制规则的添加一般就三种常见法子:写在源码里的注释、利用parasoft.suppress文件,或者是在软件的界面上右键点击报错去点Suppress。如果只有一两个明确的报错,用单行或者下一行注释弄一下就行;要是绝对不能改源码、或者项目组要统一过目,那就用抑制文件给攒起来管;要是整条规则项目都用不上,那就该回测试配置里去关掉规则,而不是到处去加抑制。