团队把一条内部编码规范写成CodeXM检查器后,往往要先在本地跑一轮,看看违规代码能不能报出来,正常写法会不会被误报。碰到结果为空时,排查得从两头入手。一头是Coverity有没有捕获到待测源码、读到这次修改的规则,另一头是规则运行后,筛选条件有没有留下预期的代码。拿几个短小的测试样例跑通,比直接翻整个项目的扫描结果省事。
一、Coverity怎么加载CodeXM检查器
CodeXM检查器以.cxm文件交给Coverity Analysis,在分析阶段随本次任务运行。这里以本地GCC编译的C文件为例,把构建捕获和加载规则分开做,便于核对每一步的输入。
1、准备检查器和待测源码
用一条限制goto语句的规则做试验,违规位置容易辨认,也方便做一份相近的正常样例。
①、把已有的检查器保存为【no_goto.cxm】,记下文件中定义的检查器名称。若规则通过【include】引用其他.cxm文件,保留它们之间的目录关系。
②、在【test_no_goto.c】里写两个简单函数,一个包含规则应当命中的【goto】语句,另一个用正常的条件分支处理。记下应报告的语句行,后面用它核对缺陷位置。
③、在终端进入样例所在目录,执行【cov-configure--template--compiler gcc】配置编译器。实际使用其他编译器时,按构建命令所用的编译器配置。
2、捕获构建并加载规则文件
①、运行【cov-build--dir cov-int gcc-c test_no_goto.c-o test_no_goto.o】,把样例的构建数据捕获到【cov-int】。接入已有项目时,将后面的GCC命令换成项目的构建命令,并确保目标源码这次确实参与编译。
②、打开【cov-int/build-log.txt】,查找【test_no_goto.c】对应的编译和捕获记录,检查有没有解析或捕获失败的信息。
③、运行【cov-analyze--dir cov-int--codexm no_goto.cxm】。同一次分析要加载多个规则文件时,为每个文件分别写一次【--codexm】。如果从其他目录启动命令,可以为检查器传入加引号的绝对路径。
3、在本地确认检查器的报告
①、运行【cov-format-errors--dir cov-int】,查看本次分析产生的缺陷。
②、按【no_goto.cxm】中定义的检查器名称查找对应报告,核对文件名、报告行和事件描述,再检查正常分支有没有被这条规则报出。
内置检查器也可能在同一次分析中产出结果。验收自定义规则时,按检查器名称和事件位置对照,比看整份报告的缺陷数量更容易判断。
二、Coverity怎么调试CodeXM检查器
分析命令跑完却没有预期的报告,可以先看规则筛到了哪些候选对象,再看报告语句有没有执行。日志能告诉你规则走到了哪一步,语法树则能帮你确认筛选条件有没有写在对应的结构上。
1、用调试输出定位筛选环节
①、打开【no_goto.cxm】,在候选对象的处理位置加一处【debug()】。可以在【let…in】表达式里用【_=debug("candidate reached")】绑定调试调用的返回值,原来的处理表达式放在【in】后面。
②、执行【cov-analyze--dir cov-int--codexm no_goto.cxm--codexm-print-debug】,在控制台查找【candidate reached】。若终端没有这条消息,先核对本次命令的调试开关和规则文件路径,再把打印点移到限制更少的候选筛选位置重跑。
③、候选位置有输出后,在条件通过的位置加第二处【debug()】,打印能区分候选对象的字段或短标签。若前一条能看到、后一条始终没有,就逐项检查条件,确认是哪一项排除了待测对象。
调试函数要配合分析命令的打印开关使用。日志内容尽量短,在候选对象多的项目里整块打印结构,反倒容易淹没样例对应的信息。
2、导出语法树核对节点和字段
肉眼看起来相近的源码写法,捕获后的结构可能有层级差别。碰到模式一直匹配不到时,可以把目标函数的结构导出来对照。
①、运行【cov-manage-emit--dir cov-int find"main"--print-codexm>codexm.json】。将【main】换成样例中实际要查找的函数名。
②、用支持折叠JSON的编辑器打开【codexm.json】,展开目标函数的【body】。沿【containedStatements】及其嵌套结构找到目标语句,核对节点类型、所在层级和规则使用的字段。
③、回到【no_goto.cxm】,每次只改一处匹配条件。重新运行带调试开关的【cov-analyze】,检查目标对象是否通过该条件,再用【cov-format-errors】确认缺陷是否落在预期位置。
三、Coverity怎么验证CodeXM检查器修改是否生效
简单样例能命中之后,还要看规则是否误报,以及换一种代码写法后有没有漏报。把样例源码和规则文件的变化分开处理,也能减少用旧数据反复调试的情况。
1、把命中与不命中的样例成对保留
①、在【test_no_goto.c】中保留一例明确违规和一例相近的合规写法。再加入一例位于嵌套代码块中的目标语句,按项目约定写明它是否应当报告。
②、改动样例源码后,用【cov-build】捕获到新的中间目录,再把【cov-analyze】和【cov-format-errors】的目录参数都指向这份数据。
③、逐个对照样例和【缺陷报告】,核查应报位置有没有漏掉、合规写法有没有误报。若同一语句出现多条报告,回到规则的匹配和报告部分,检查同一对象是否被重复处理。
2、把验证过的规则接回项目分析
①、在项目的分析脚本中找到【cov-analyze】,把验证过的规则文件加入【--codexm】参数。若文件通过【include】引用其他规则,同步保留依赖文件的相对位置。
②、在项目扫描环境中执行一次任务,核对【分析日志】里的实际规则路径和中间目录,再按检查器名称检查生成的缺陷。
③、样例源码和编译参数保持原样、只修改了【no_goto.cxm】时,可以复用原来的捕获数据,重新分析并生成报告。日常扫描脚本中移除【--codexm-print-debug】,将调试输出留给本地试验。
总结
加载CodeXM检查器时,规则文件和捕获数据要对应到本次分析。调试时,控制台日志用来确认筛选走到了哪里,语法树用来核对匹配条件,缺陷报告用来验收结果。留下一组能命中、应放行的对照样例,今后改动规则时就有了可复查的依据。大家遇到某种写法一直漏报时,也可以先把它缩成一个短函数,看看它和已经能命中的样例差在哪一层。
