CodeChecker是基于LLVM/Clang Static Analyzer工具链的一个静态分析框架,替代了linux或者mac里的scan-build。
github仓库:https://github.com/Ericsson/codechecker
文档:https://codechecker.readthedocs.io/en/latest/
简介
CodeChecker在github仓库有1.6k的star。文档也提出这是一个框架,意味着它可以整合很多的静态工具,包括cppcheck和infer等等,还有java,python的静态分析器。本文主要用的是clang-tidy和clang static analyzer这两个。
安装
pip3 install codechecker
要直接在命令行使用的话,需要设置下环境变量。
使用
CodeChecker的步骤可以分为三步:
- log:运行程序的build命令,记录编译的过程。这些过程会被导出为json格式。
- analyze:基于前面的json文件来对程序进行分析,并输出结果。
- postprocess:对结果做处理
- parse:解析分析的结果,输出好看的summary和结果。
- store:存储结果到正在运行的codechecker 服务器
- cmd diff:比较两个分析结果,并展示差别
- etc …
step1:log
现在结合一个实例来用用看codechecker。还是用libpng来试试。
首先,清理掉之前编译的结果。
make clean
然后使用codechecker 记录build 命令
./configure --disable-shared
CodeChecker log --build "make" --output ./compile_commands.json
运行完该命令后,可以看看这个json文件都是啥玩意。从下图可以很明显知道,这个log的过程实际上就是确定要分析哪些源代码文件。
step2:analyze
接着,就可以开始下一步分析了。输入如下命令即可开始分析。
CodeChecker analyze ./compile_commands.json --enable sensitive --output ./reports
enable sensitive以实是开启了部分的checker,也就是能够检测某些漏洞。如果想看更多的checker,可以输入下面的命令
# 列举所有可用的checker
CodeChecker checkers --help
# 显示checker的具体信息
CodeChecker checkers --detail
# 显示checker的组,比如前面指的sensitive
CodeChecker checkers --profile --details
# 显示属于sensitive 的checker
CodeChecker checkers --profile sensitive --details
可以看到终端输出如下信息:
[INFO 2022-08-09 06:06] - Enabled checkers:
clang-tidy: boost-use-to-string, bugprone-argument-comment, bugprone-assert-side-effect, bugprone-bad-signal-to-kill-thread, bugprone-bool-pointer-implicit-conversion, bugprone-branch-clone, bugprone-copy-constructor-init, bugprone-dangling-handle, bugprone-dynamic-static-initializers, bugprone-exception-escape, bugprone-fold-init-type, bugprone-forward-declaration-namespace, bugprone-forwarding-reference-overload, bugprone-inaccurate-erase, bugprone-incorrect-roundings, bugprone-infinite-loop, bugprone-integer-division, bugprone-lambda-function-name, bugprone-macro-parentheses, bugprone-macro-repeated-side-effects, bugprone-misplaced-operator-in-strlen-in-alloc, bugprone-misplaced-pointer-arithmetic-in-alloc, bugprone-misplaced-widening-cast, bugprone-move-forwarding-reference, bugprone-multiple-statement-macro, bugprone-narrowing-conversions, bugprone-no-escape, bugprone-not-null-terminated-result, bugprone-parent-virtual-call, bugprone-posix-return, bugprone-redundant-branch-condition, bugprone-reserved-identifier, bugprone-signal-handler, bugprone-signed-char-misuse, bugprone-sizeof-container, bugprone-sizeof-expression, bugprone-spuriously-wake-up-functions, bugprone-string-constructor, bugprone-string-integer-assignment, bugprone-string-literal-with-embedded-nul, bugprone-suspicious-enum-usage, bugprone-suspicious-include, bugprone-suspicious-memset-usage, bugprone-suspicious-missing-comma, bugprone-suspicious-semicolon, bugprone-suspicious-string-compare, bugprone-swapped-arguments, bugprone-terminating-continue, bugprone-throw-keyword-missing, bugprone-too-small-loop-variable, bugprone-undefined-memory-manipulation, bugprone-undelegated-constructor, bugprone-unhandled-self-assignment, bugprone-unused-raii, bugprone-unused-return-value, bugprone-use-after-move, bugprone-virtual-near-miss, cert-con36-c, cert-con54-cpp, cert-dcl03-c, cert-dcl16-c, cert-dcl21-cpp, cert-dcl37-c, cert-dcl50-cpp, cert-dcl51-cpp, cert-dcl54-cpp, cert-dcl58-cpp, cert-dcl59-cpp, cert-env33-c, cert-err09-cpp, cert-err34-c, cert-err52-cpp, cert-err58-cpp, cert-err60-cpp, cert-err61-cpp, cert-fio38-c, cert-flp30-c, cert-mem57-cpp, cert-msc30-c, cert-msc32-c, cert-msc50-cpp, cert-msc51-cpp, cert-oop11-cpp, cert-oop54-cpp, cert-oop57-cpp, cert-oop58-cpp, cert-pos44-c, cert-sig30-c, cert-str34-c, cppcoreguidelines-pro-type-const-cast, cppcoreguidelines-pro-type-static-cast-downcast, cppcoreguidelines-slicing, cppcoreguidelines-special-member-functions, google-build-explicit-make-pair, google-build-namespaces, google-build-using-namespace, google-explicit-constructor, google-global-names-in-headers, google-runtime-int, google-runtime-operator, misc-definitions-in-headers, misc-misplaced-const, misc-redundant-expression, misc-unconventional-assign-operator, misc-uniqueptr-reset-release, misc-unused-alias-decls, misc-unused-using-decls, modernize-deprecated-headers, modernize-replace-auto-ptr, modernize-replace-random-shuffle, mpi-buffer-deref, mpi-type-mismatch, performance-faster-string-find, performance-for-range-copy, performance-implicit-conversion-in-loop, performance-inefficient-algorithm, performance-inefficient-string-concatenation, performance-inefficient-vector-operation, performance-move-const-arg, performance-move-constructor-init, performance-no-automatic-move, performance-no-int-to-ptr, performance-noexcept-move-constructor, performance-trivially-destructible, performance-type-promotion-in-math-fn, performance-unnecessary-copy-initialization, performance-unnecessary-value-param
clangsa: alpha.core.BoolAssignment, alpha.core.CastSize, alpha.core.Conversion, alpha.core.DynamicTypeChecker, alpha.core.SizeofPtr, alpha.core.TestAfterDivZero, alpha.cplusplus.DeleteWithNonVirtualDtor, alpha.cplusplus.EnumCastOutOfRange, alpha.cplusplus.InvalidatedIterator, alpha.cplusplus.IteratorRange, alpha.cplusplus.MismatchedIterator, alpha.cplusplus.STLAlgorithmModeling, alpha.cplusplus.SmartPtr, alpha.security.MmapWriteExec, alpha.security.ReturnPtrRange, alpha.security.cert.pos.34c, alpha.security.taint.TaintPropagation, alpha.unix.BlockInCriticalSection, alpha.unix.Chroot, alpha.unix.PthreadLock, alpha.unix.Stream, alpha.unix.cstring.NotNullTerminated, alpha.unix.cstring.OutOfBounds, core.CallAndMessage, core.DivideZero, core.NonNullParamChecker, core.NullDereference, core.StackAddressEscape, core.UndefinedBinaryOperatorResult, core.VLASize, core.uninitialized.ArraySubscript, core.uninitialized.Assign, core.uninitialized.Branch, core.uninitialized.CapturedBlockVariable, core.uninitialized.UndefReturn, cplusplus.InnerPointer, cplusplus.Move, cplusplus.NewDelete, cplusplus.NewDeleteLeaks, cplusplus.PlacementNew, cplusplus.PureVirtualCall, deadcode.DeadStores, nullability.NullPassedToNonnull, nullability.NullReturnedFromNonnull, nullability.NullableDereferenced, nullability.NullablePassedToNonnull, nullability.NullableReturnedFromNonnull, optin.cplusplus.UninitializedObject, optin.cplusplus.VirtualCall, optin.mpi.MPI-Checker, optin.portability.UnixAPI, security.FloatLoopCounter, security.insecureAPI.UncheckedReturn, security.insecureAPI.getpw, security.insecureAPI.gets, security.insecureAPI.mkstemp, security.insecureAPI.mktemp, security.insecureAPI.rand, security.insecureAPI.vfork, unix.API, unix.Malloc, unix.MallocSizeof, unix.MismatchedDeallocator, unix.Vfork, unix.cstring.BadSizeArg, unix.cstring.NullArg, valist.CopyToSelf, valist.Uninitialized, valist.Unterminated
[INFO 2022-08-09 06:06] - Starting static analysis ...
[INFO 2022-08-09 06:06] - [1/60] clang-tidy analyzed pngrio.c successfully.
...
[INFO 2022-08-09 06:06] - [58/60] clangsa analyzed png.c successfully.
[WARNING 2022-08-09 06:06] - Previous analysis results in '/home/iskindar/Project/StaticReportAnalyzer/testbench/libpng/repo/reports/png.c_clangsa_434fc486b6e177fd54310eb11a3482b3.plist' has been overwritten.
[INFO 2022-08-09 06:06] - [59/60] clangsa analyzed pngfix.c successfully.
[WARNING 2022-08-09 06:06] - Previous analysis results in '/home/iskindar/Project/StaticReportAnalyzer/testbench/libpng/repo/reports/pngfix.c_clangsa_ba07ed53654a4d59ca58c53e53b2c2af.plist' has been overwritten.
[INFO 2022-08-09 06:06] - [60/60] clangsa analyzed pngrutil.c successfully.
[WARNING 2022-08-09 06:06] - Previous analysis results in '/home/iskindar/Project/StaticReportAnalyzer/testbench/libpng/repo/reports/pngrutil.c_clangsa_833aa45b93bfffdc4e1c822fc1cd1e66.plist' has been overwritten.
[INFO 2022-08-09 06:06] - ----==== Summary ====----
[INFO 2022-08-09 06:06] - Successfully analyzed
[INFO 2022-08-09 06:06] - clang-tidy: 30
[INFO 2022-08-09 06:06] - clangsa: 30
[INFO 2022-08-09 06:06] - Reanalyzed compilation commands: 30
[INFO 2022-08-09 06:06] - Total analyzed compilation commands: 30
[INFO 2022-08-09 06:06] - ----=================----
[INFO 2022-08-09 06:06] - Analysis finished.
[INFO 2022-08-09 06:06] - To view results in the terminal use the "CodeChecker parse" command.
[INFO 2022-08-09 06:06] - To store results use the "CodeChecker store" command.
[INFO 2022-08-09 06:06] - See --help and the user guide for further options about parsing and storing the reports.
[INFO 2022-08-09 06:06] - ----=================----
[INFO 2022-08-09 06:06] - Analysis length: 22.119323253631592 sec.
然后可以看到当前目录的report文件下有以下这些plist文件。
pngwtran.c_clang-tidy_b72547538acb76955b4cb5907edea56d.plist
pngwutil.c_clangsa_e7f13b748da8247ecb13767160fed60e.plist
pngwutil.c_clang-tidy_e7f13b748da8247ecb13767160fed60e.plist
powerpc_init.c_clangsa_0640f12de3b39e9beee8114e182365ed.plist
powerpc_init.c_clang-tidy_0640f12de3b39e9beee8114e182365ed.plist
timepng.c_clangsa_b7c3f136c01c6bbeb39bfdbc200c1576.plist
timepng.c_clang-tidy_b7c3f136c01c6bbeb39bfdbc200c1576.plist
...
这些plist文件的内容是xml文件,直接看可读性有点差。
看到这里,发现文档说可以把步骤1和步骤2合成为一个命令:
CodeChecker check --jobs 22 --build "make clean ; make --jobs 4" \
--output ./reports --clean --enable sensitive
step3:后续处理
可以使用parse命令把它解析下
CodeChecker parse ./reports
可以看到如下的内容,包括每个报告的具体行号以及最后的summary。
[MEDIUM] /home/iskindar/Project/StaticReportAnalyzer/testbench/libpng/repo/png.h:586:38: macro replacement list should be enclosed in parentheses [bugprone-macro-parentheses]
#define PNG_TEXT_COMPRESSION_NONE_WR -3
^
[MEDIUM] /home/iskindar/Project/StaticReportAnalyzer/testbench/libpng/repo/png.h:587:38: macro replacement list should be enclosed in parentheses [bugprone-macro-parentheses]
#define PNG_TEXT_COMPRESSION_zTXt_WR -2
^
[MEDIUM] /home/iskindar/Project/StaticReportAnalyzer/testbench/libpng/repo/png.h:588:38: macro replacement list should be enclosed in parentheses [bugprone-macro-parentheses]
#define PNG_TEXT_COMPRESSION_NONE -1
^
...
----==== Severity Statistics ====----
----------------------------
Severity | Number of reports
----------------------------
MEDIUM | 63
LOW | 55
HIGH | 5
----------------------------
----=================----
----==== Checker Statistics ====----
----------------------------------------------------------------
Checker name | Severity | Number of reports
----------------------------------------------------------------
bugprone-macro-parentheses | MEDIUM | 21
cert-err34-c | LOW | 5
bugprone-reserved-identifier | LOW | 12
cert-dcl37-c | LOW | 12
cert-dcl51-cpp | LOW | 12
alpha.security.ReturnPtrRange | HIGH | 1
performance-no-int-to-ptr | LOW | 3
bugprone-branch-clone | LOW | 7
unix.Malloc | MEDIUM | 1
bugprone-narrowing-conversions | MEDIUM | 31
deadcode.DeadStores | LOW | 4
bugprone-signed-char-misuse | MEDIUM | 3
cert-str34-c | MEDIUM | 3
alpha.unix.Stream | MEDIUM | 3
core.NullDereference | HIGH | 1
cert-dcl03-c | MEDIUM | 1
bugprone-suspicious-missing-comma | HIGH | 1
core.NonNullParamChecker | HIGH | 2
----------------------------------------------------------------
----=================----
----==== File Statistics ====----
----------------------------------
File name | Number of reports
----------------------------------
png.h | 5
pngget.c | 4
pngpriv.h | 8
pngtest.c | 3
powerpc_init.c | 3
pngerror.c | 3
pngstest.c | 6
pngread.c | 1
pngrutil.c | 4
pngmem.c | 2
pngset.c | 8
png.c | 11
mips_init.c | 3
pngimage.c | 12
timepng.c | 3
pngfix.c | 27
pngrtran.c | 1
pngpread.c | 1
pngvalid.c | 15
pngcp.c | 3
----------------------------------
----=================----
----======== Summary ========----
-----------------------------------------------
Number of processed analyzer result files | 60
Number of analyzer reports | 123
-----------------------------------------------
----=================----
当然也可以解析为html
CodeChecker parse --export html --output ./reports_html ./reports
打开网页可以看到以下这些信息,还有路径的长度。
除了html外,也可以导出为json,codeclimate等格式
export arguments:
-e {html,json,codeclimate,gerrit,baseline}, --export {html,json,codeclimate,gerrit,baseline}
Specify extra output format type.
'codeclimate' format can be used for Code Climate and for GitLab integration. For more
information see:
https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#data-types
'baseline' output can be used to integrate CodeChecker into your local workflow without using a
CodeChecker server. For more information see our usage guide. (default: None)
到此本文基本结束了,但codechecker还有很多有意思的内容没有介绍,就需要读者自己看文档琢磨了。(虽然文章的主要目的是记录,以防后面自己又要回过头来用这个工具)
其他有意思的内容暂且记录如下:
- 自动修复:CodeChecker fixit ./reports
- diff
- 如何整合其他的静态工具