Zephyr支持静态代码分析工具

Creative Commons
本作品采用知识共享署名

本文介绍Zephyr对静态代码分析工具的支持情况。

静态分析工具用于直接扫描代码,通过对代码的分析找出诸如内存泄漏或缓冲区溢出等常见的已知错误和漏洞。商用专业的静态代码分析工具还可以按照指定的编码标准进行扫描分析。
在正规的开发中CI/CD过程会加入静态代码分析用于预先防范代码漏洞,在一般的开发编码过程中也可以使用静态代码分析工具帮助我们查找编码的疏漏。Zephyr v3.3.0开始引入了对静态编码工具(Static Code Analysis 后面简称SCA)的支持,在使用west构建时SCA同时工作进行代码扫描,并提示错误

Zephyr原生支持的SCA

Zephyr原生支持sparse作为自己的SCA,只用在构建的时候通过ZEPHYR_SCA_VARIANT指定spare即可,具体方法如下

1
west build -b mm_feather zephyr/samples/hello_world -- -DZEPHYR_SCA_VARIANT=sparse

构建+过程中可能会提示找不到cgcc,这是因为没有安装sparse, ubuntu下执行下面命令进行安装

1
sudo apt-get install sparse

sparse是linus为kernel开发的一个静态代码分析工具,其核心功能有限,主要用于检查不同地址空间指针的混用。
https://www.kernel.org/doc/html/latest/dev-tools/sparse.html

SCA工具的支持和添加

Zephyr通过cmake完成对SCA工具的集成和支持,主要的内容在如下文件/文件夹中,可以通过查找关键字SPARSE, SCA_ROOT, ZEPHYR_SCA_VARIANT找到相关内容
cmake/modules/FindDeprecated.cmake
cmake/modules/FindScaTools.cmake
cmake/modules/kernel.cmake
cmake/modules/root.cmake
cmake/sca/sparse/

对sparse的原生支持

对sparse的支持通过cmake/sca/sparse来指定,可以通过修改其sca.cmake来改变配置

SCA工具的添加

对 SCA 工具的支持在sca.cmake 文件中实现。 该文件放在<SCA_ROOT>/cmake/sca/<tool>/sca.cmake。 Zephyr 默认将自己的代码目录做为SCA_ROOT, 我们新加SCA tool也可以放在zephyr/cmake/sca
例如要添加cppcheck作为sca
1 建立cppcheck

1
2
3
4
5
zephyr/                 # zephyr代码目录
└── cmake/
└── sca/
└── cppcheck/ # SCA工具名, 构建时提供给 ZEPHYR_SCA_VARIANT
└── sca.cmake # sca 工具配置

实际项目中为了不污染zephyr的代码目录,我们会另外指定路径

1
2
3
4
5
/mnt/g/project/zephyrproject/sca                # 自定义的SCA_ROOT, 构建时指定
└── cmake/
└── sca/
└── cppcheck/ # SCA工具名, 构建时提供给 ZEPHYR_SCA_VARIANT
└── sca.cmake # sca 工具配置

2 配置cppcheck
sca.cmake的内容如下

1
2
3
4
5
6
7
8
9
find_program(CPPCHECK_TOOL cppcheck)
set(CMAKE_C_CPPCHECK
${CPPCHECK_TOOL}
--enable=warning
--inconclusive
--force
--inline-suppr
CACHE INTERNAL ""
)

3 运行&结果
指定ZEPHYR_SCA_VARIANT为cppcheck,同时因为配置文件放到外部文件夹需要做SCA_ROOT指定

1
west build -b mm_feather zephyr/samples/hello_world -- -DZEPHYR_SCA_VARIANT=cppcheck -DSCA_ROOT=/mnt/g/project/zephyrproject/sca

我们的示例代码main.c为

1
2
3
4
5
6
7

void main(void)
{
int a[5];
a[5] = 32;
printk("Hello World! %s\n", CONFIG_BOARD);
}

构建过程中会提示, 可以看到会指出数组a操作出界

1
2
3
4
5
6
7
Checking /mnt/g/project/zephyrproject/zephyr/samples/hello_world/src/main.c: BOARD_FLASH_SIZE=CONFIG_FLASH_SIZE*1024;CPU_MIMXRT1062DVL6A=1;KERNEL=1;NDEBUG=1;XIP_BOOT_HEADER_DCD_ENABLE=1;XIP_BOOT_HEADER_ENABLE=1;XIP_EXTERNAL_FLASH=1;__PROGRAM_START=1;__ZEPHYR__=1;_ASMLANGUAGE...
Checking /mnt/g/project/zephyrproject/zephyr/samples/hello_world/src/main.c: BOARD_FLASH_SIZE=CONFIG_FLASH_SIZE*1024;CPU_MIMXRT1062DVL6A=1;KERNEL=1;NDEBUG=1;XIP_BOOT_HEADER_DCD_ENABLE=1;XIP_BOOT_HEADER_ENABLE=1;XIP_EXTERNAL_FLASH=1;__PROGRAM_START=1;__ZEPHYR__=1;_ASMLANGUAGE;__ASSEMBLER__...
/mnt/g/project/zephyrproject/zephyr/samples/hello_world/src/main.c:12:3: error: Array 'a[5]' accessed at index 5, which is out of bounds. [arrayIndexOutOfBounds]
a[5] = 32;
^
[5/14] Linking C static library app/libapp.a
[6/14] Linking C executable zephyr/zephyr_pre0.elf

参考

https://docs.zephyrproject.org/latest/develop/sca/index.html