iOS 测试 infer 静态代码扫描学习 总结

彤彤彤彤彤 · 2021年08月23日 · 最后由 彤彤彤彤彤 回复于 2021年10月16日 · 6539 次阅读

infer 官方文档:https://fbinfer.com/

infer 是 facebook 开源的一款静态代码扫描工具(支持 objective-C、C++,Java 代码)

一.infer 安装
前提:需非 m1 芯片的电脑(自己 m1 芯片电脑尝试了很多种方法暂未安装成功,换了非 m1 芯片一安装就安装成功了)
一行命令即可完成安装:

brew install infer

安装后配置环境变量:

echo "export PATH=\"\$PATH:pwd/infer/infer/bin\"" \ >> ~/.bash_profile &&source ~/.bash_pr

其他安装 xcode 命令行工具

sudo rm -rf /Library/Developer/CommandLineTools
sudo xcode-select --install
xcodebuild -version

(报错参考文章https://blog.csdn.net/li15809284891/article/details/79629190)

二.infer 命令使用(iphonesimulator 是模拟器编译,真机用 iphoneos 如:iphoneos14.5 )
第一种方式:Infer 提供了与 xcodebuild 的直接集成
【非 pod 项目】

infer run -- xcodebuild -target xx -configuration xx -sdk iphonesimulator  

【pod 项目】

infer run -- xcodebuild -workspace xx.xcworkspace -scheme xx -configuration Debug -sdk iphonesimulator

第二种:最健壮的方法是生成一个编译数据库,然后将该数据库传递给 Infer
(我公司的项目第一种方式总报错,网上求助了大佬,告诉我用第二种方式)
1、先编译数据 database( -arch x86_64 COMPILER_INDEX_STORE_ENABLE=NO 参数可以不用加)

xcodebuild -workspace xx.xcworkspace -scheme xx -sdk iphonesimulator  -arch x86_64 COMPILER_INDEX_STORE_ENABLE=NO| tee xcodebuild.log | xcpretty -r json-compilation-database -o compile_commands.json

2、再执行 infer 指令

infer run --keep-going --skip-analysis-in-path Pods --compilation-database-escaped compile_commands.json

本人尝试这个 xcodebuild clean 命令,无法清除缓存,要使用下面的命令

xcodebuild -scheme xx -workspace xx.xcworkspace clean 

三、生成报告
扫描后执行

infer-explore --html

四、工作流程

PS:不管是分析哪种语言,Infer 运行时,分为两个主要阶段:
1.捕获阶段:Infer 捕获编译命令,将文件翻译成 Infer 内部的中间语言

这就是我们调用 Infer 时带上一个编译命令的原因了比如: infer -- clang -c file.c结果就是文件照常编译同时被 Infer 翻译成中间语言留作第二阶段处理特别注意的就是如果没有文件被编译那么也没有任何文件会被分析

2.分析阶段:Infer 分析 infer-out/ 下的所有文件。分析时,会单独分析每个方法和函数。

在分析一个函数的时候如果发现错误将会停止分析但这不影响其他函数的继续分析
错误除了会显示在标准输出之外还会输出到文件 infer-out/bug.txt 我们过滤这些问题仅显示最有可能存在的

默认情况下,每次运行 infer 命令都会删除之前的 infer-out 文件夹。你可以通过 --incremental 参数使用增量模式。增量模式下,运行 infer 命令不会删除 infer-out 文件夹,但是会利用这个文件夹进行 diff,减少分析量。一般进行全新一轮分析时直接使用默认的非增量模式,而对于只想分析修改部分情况时,就使用增量模式。

五、增量&非增量

增量模式和非增量模式

六、添加过滤文件
第一种,分析带 cocoapods 的项目,在工程目录下新建 .inferconfig 文件

{
"skip-analysis-in-path":["Pods"]
}
{
"infer-whitelist-path-regex":[
],
"infer-blacklist-path-regex":[
"Pods/AFNetworking",
"Pods/SDWebImage"
]
}

第二种,在命令行里添加过滤条件
1.in-path 后面跟的是一个忽略文件或者文件夹的路径数组
2.["Pods"] 代表过滤所有的 Pods 文件
3.["Pods/AFNetworking","Pods/Masonry"] 代表过滤 AFNetworking、Masonry 三方库
4.也可以写个脚本对解析出来的文件进行二次拆分,按组件模块、错误和警告划分

--skip-analysis-in-path Pods

================================================================
PS: 遇到的坑

1.使用 m1 芯片的电脑安装 infer,无法安装成功
解决办法:换成非 m1 芯片的 mac 本,成功解决
2.使用

infer run -- xcodebuild -workspace xx.xcworkspace -scheme xx -configuration Debug -sdk iphonesimulator

命令会报错,报错如下

xternal Error: *** capture failed to execute: exited with code 65
Error backtrace:
Raised at Stdlib.input_line.scan in file "stdlib.ml", line 449, characters 14-31
Called from Stdio__In_channel.input_line_exn in file "src/in_channel.ml" (inlined), line 68, characters 13-30
Called from IBase__Utils.with_channel_in in file "src/base/Utils.ml", line 260, characters 11-44
Re-raised at IBase__Die.raise_error.do_raise in file "src/base/Die.ml", line 26, characters 8-56
Called from Integration__Driver.capture in file "src/integration/Driver.ml", line 145, characters 6-36
Called from IBase__Utils.timeit in file "src/base/Utils.ml", line 429, characters 16-20
Called from IBase__ScubaLogging.execute_with_time_logging in file "src/base/ScubaLogging.ml", line 79, characters 29-44
Called from Backend__GCStats.log_f in file "src/backend/GCStats.ml", line 90, characters 10-14
Called from Dune__exe__Infer.run in file "src/infer.ml", line 20, characters 2-36
Called from IBase__Utils.timeit in file "src/base/Utils.ml", line 429, characters 16-20
Called from IBase__ScubaLogging.execute_with_time_logging in file "src/base/ScubaLogging.ml", line 79, characters 29-44
Called from Dune__exe__Infer.run in file "src/infer.ml", line 25, characters 22-94

Run the command again with `--keep-going` to try and ignore this error.
69324: Error while running epilogue "Stop Sqlite write daemon":
(Unix.Unix_error "No such file or directory" connect
 "((addr (ADDR_UNIX sqlite_write_socket)))").

解决办法:使用第二种生成中间数据库的方式,解决(见上文)

3.无法用模拟器生成 database 文件,可以用真机命令生成
解决办法:

4.执行过程中 找不到报 arm64
解决办法:

5.报 '-index-store-path' 错误

Error message:clang-8: error: unknown argument: '-index-store-path'*** Infer needs a working compilation command to run.
clang-8: error: unknown argument: '-index-store-path' 

网上的解决办法: 由于从 Xcode 9.0 开始将-index-store-path 参数添加到构建命令中。而 infer 所依赖的 clang 还不支持此参数。在项目 Build Setting 中搜索 index 并将 Enable Index-While-Building Functionality 选项设置为 NO
我这边采用网上的解决办法不生效,于是在生成中间文件的时候加了 COMPILER_INDEX_STORE_ENABLE=NO 的参数就解决了

6.第一次能扫出来全的报告(生成的 compile_commands.json 也比较全),第二次执行时输入 xcodebuild clean 后,在手动删除 inferout 文件夹、xcodebuild.log、build、compile_commands.json 在依次运行命令,扫出来的问题不全(生成的 compile_commands.json 明显很少,好像有缓存没清除掉)
解决办法:不要用 xcodebuild clean ,改为下面的

xcodebuild -scheme xx -workspace xx.xcworkspace clean 

jenkins 进行 infer 静态扫描,给工作群发送报告通知
https://testerhome.com/topics/30912

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 1 条回复 时间 点赞

{
"skip-analysis-in-path":["Pods"],
"disable-issue-type": ["DEAD_STORE"],
"disable-issue-type": ["STRONG_SELF_NOT_CHECKED"],
"disable-issue-type": ["MULTIPLE_WEAKSELF"],
"disable-issue-type": ["NULL_DEREFERENCE"],
"disable-issue-type": ["CAPTURED_STRONG_SELF"],
"disable-issue-type": ["POINTER_TO_CONST_OBJC_CLASS"],
"report-blacklist-path-regex":["Pods"]
}

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册