C/C++代码静态分析工具调研
C/C++代码静态分析工具调研
简述
静态分析(static analysis)是指在不执行代码的情况下对其进行分析评估的过程,是软件质量和软件安全保障的重要一环。它通过词法分析、语义分析、控制流分析、数据流分析等技术对代码逐行解析暴露问题,从而协助我们将许多在运行时才会暴露的棘手麻烦扼杀于摇篮之中。
典型问题示例
代码静态分析能够识别诸多类型的漏洞或缺陷,轻至警告级的「变量未使用」,重至错误级的各类bug,这里列举几种常见的、较严重的、可静态检测的问题。
■ 缓冲区溢出
缓冲区溢出是指向缓冲区中存入超出其空间大小的数据量,导致多余的数据覆盖其他区域的合法数据,类似倒入容器中的水过多而导致溢出,流到它不该去的地方,造成不可预期的后果。从实践统计看,缓冲区溢出问题是软件中最普遍存在的漏洞问题,在C/C++这类不提供内存越界检测的语言中尤甚。通常,发生缓冲区溢出的情况有:
- 字符串拷贝,当目标缓冲区长度小于源字串的长度时(此类的函数包括
strcpy
、_mbscpy
、strcat
、wcscat
、memcpy
、strncpy
、_mbsncpy
、strncat
、wcsncat
等)。
// 字符串拷贝之前没有对s做长度判断,如果超过10,就会造成缓冲区溢出。
void func(char* s)
{
char buf[10];
strcpy(buf, s);
}
- 格式化字符串处理,当参数与格式化字符串不匹配时(此类的函数包括
printf
、fprintf
、sprintf
、swprintf
等)。
// %n将前面打印的字串长度信息写到相应地址
int len = 0;
printf("This is a test string.%n", &len);
// 错误的写法,此时长度信息会写到地址为0的内存空间中
int len = 0;
printf("This is a test string.%n", len);
- 字符串读取,当缓冲区小于所要读入的字符串长度时(此类的函数包括
scanf
、fscanf
、sscanf
、gets
、getc
、fgets
、fgetc
等)。
// 用户输入的字串长度不受控制,如果超过10,就会造成缓冲区溢出。
char buf[10];
scanf("%s", &buf);
■ 内存泄漏
内存泄漏一般指堆内存的泄漏(也有系统资源的泄漏),程序申请的内存资源没有被合理地释放,导致这部分内存不能被回收利用而造成资源的浪费。严重时,过多的内存泄漏会造成系统崩溃。C/C++语言没有自动回收机制,需要程序员自行确保内存使用的闭环(new/delete
、alloc/free
、malloc/free
、GlobalAlloc/GlobalFree
成对使用)。
通常,发生内存泄漏的情况有:
- 分配内存后忘了调用相应的释放函数。
- 过程因达到某种条件提前结束,未能执行后面的内存释放函数。
- 程序设计不合理,不断分配内存,到最后才一起释放,虽然整体上不算内存泄漏,但在过程中已经酝酿了资源耗尽的可能性,无异于内存泄漏。
■ 野指针
当指针变量未被初始化,或指向的内存已被回收时,该指针便成了野指针。其指向的内存地址是非法的,对这块非法区域进行操作将导致不可预料的后果。
// 对指针是否为空的判断看是严谨,其实是无效的。
char *p = (char*)malloc(10);
free(p);
if (p != NULL)
{
strcpy(p, "danger");
}
工具调研
根据工作需要,从可检测的语言、使用平台和授权三方面考量,调研了20余种主流的C/C++代码静态分析工具。
工具 | 语言 | 平台 | 授权 |
---|---|---|---|
AdLint | C | Windows, Linux, Mac OS, FreeBSD | 开源 |
Astrée | C | Windows, Linux | 付费 |
Bauhaus Toolkit | C, C++, Java, C#, Ada | Windows, Linux, Solaris | 付费 |
BLAST | C | Linux | 开源 |
Cppcheck | C, C++ | Windows, Linux | 开源 |
Coccinelle | C | Linux | 开源 |
Coverity | C, C++, C#, Java, JS, PHP, Python, Objective-C, Ruby, Swift, Fortran, VB | Windows, Linux, Mac OS, FreeBSD, Solaris | 付费 |
CppDepend | C, C++ | Windows, Linux | 付费 |
ECLAIR | C, C++ | Windows, Linux, Mac OS | 付费 |
Flawfinder | C, C++ | Python | 开源 |
Fluctuat | C, Ada | Windows, Linux, Mac OS, FreeBSD | 付费 |
Frama-C | C | Windows, Linux, Mac OS, FreeBSD | 开源/付费 |
CodeSonar | C, C++, Java, 二进制码 | Windows, Linux, Mac OS, FreeBSD | 付费 |
Klocwork | C, C++, Java, C# | Windows, Linux, Solaris | 付费 |
LDRA Testbed | C, C++, Java, Ada | Windows, Linux, Mac OS | 付费 |
Parasoft C/C++test | C, C++ | Windows, Linux, Solaris | 付费 |
PC-Lint | C, C++ | Windows | 付费 |
Polyspace | C, C++, Ada | Windows, Linux, Mac OS | 付费 |
PRQA QA·Static Analyzers | C, C++, Java | Windows, Linux | 付费 |
SLAM | C | Windows | 免费 |
Sparse | C | Linux, Mac OS, BSD | 开源 |
Splint | C | Linux, FreeBSD, Solaris | 开源 |
TscanCode | C, C++, C#, Lua | Windows, Linux, Mac OS | 开源 |
根据以下标准,筛选出3款适用性较高的工具——Cppcheck、Flawfinder、TscanCode——进行详细调研:
- 语言:支持C/C++代码分析
- 平台:支持在Windows和/或Linux平台运行
- 授权:免费
为进行一次实践对比,从TscanCode的GitHub上抓到一组现成的C/C++编码问题示例,共94个CPP文件,考察三者的检测效果。
运行平台:Windows
被测语言:C/C++
测试集:TscanCode/samples/cpp
■ Cppcheck
Cppcheck可检测的问题包括:
- Dead pointers
- Division by zero
- Integer overflows
- Invalid bit shift operands
- Invalid conversions
- Invalid usage of STL
- Memory management
- Null pointer dereferences
- Out of bounds checking
- Uninitialized variables
- Writing const data
并将问题分为以下6类:
- 错误(error):bug。
- 警告(warning):预防性编程方面的建议。
- 风格警告(style):出于对代码简洁性的考虑(函数未使用、冗余代码等)。
- 可移植性警告(portability):64/32位可移植性、编译器通用性等。
- 性能警告(performance):使代码更高效的建议,但不保证一定有明显效果。
- 信息消息(information):条件编译方面的警告。
安装十分简便,只需在官网下载最新的可执行安装包(本文目前为cppcheck-1.83-x86-Setup.msi
)跟着向导「下一步」即可。
除了GUI,Cppcheck还支持与多种IDE(如VS、Eclipse、QtCreator等)、版本管理系统(如Tortoise SVN、Git)集成使用。
可对每次分析进行配置甚至自定义规则,并作为项目文件进行保存或重载。
分析的结果报告可保存为格式化纯文本或XML,并可借助Python pygments将XML生成为HTML。
■ TscanCode
TscanCode是腾讯的开源项目,为此次调研的唯一一款本土工具,起初构建于Cppcheck的基础之上,后来进行了重新实现,并加入了对C#和Lua的支持。
TscanCode可检测的问题包括:
- 空指针检查,包含可疑的空指针,判空后解引用比如Crash等共3类subid检查
- 数据越界,Sprintf_S越界共1类subid检查
- 内存泄漏,分配和释放不匹配同1类subid检查
- 逻辑错误,重复的代码分支,bool类型和INT进行比较,表达式永远True或者false等共18类检查
- 可疑代码检查,if判断中含有可疑的=号,自由变量返回局部变量等共计15类检查
- 运算错误,判断无符号数小于0,对bool类型进行++自增等,共计11类检查
并将问题分为致命、严重、警告、提示、风格5类。
安装同样便捷,下载安装包(本文目前为TscanCodeV2.14.24.windows.exe
)跟着向导「下一步」即可。
TscanCode的提示信息可以说直接照搬了Cppcheck,但给出的提示数量明显少于Cppcheck,以mismatchsize.cpp
为例:
void Demo()
{
//分配的内存空间不匹配
int i = malloc(3);
}
■ Flawfinder
Flawfinder由计算机安全专家David A. Wheeler个人开发,依托于Python,自然而然拥有了跨平台性。
安装:
pip install flawfinder
运行:
cd *python_path*/Scripts
python flawfinder *directory_with_source_code*
实践表明,Flawfinder对中文注释更不友好,直接拿TscanCode的测试集跑会报编码错误,尽管这些CPP文件本来就是Flawfinder文档所建议的UTF-8格式:
UnicodeDecodeError: 'gbk' codec can't decode byte 0xaf in position 92: illegal multibyte sequence
将测试集批量转换为ANSI格式后方可正常运行:
David A. Wheeler本人也在官网特别声明Flawfinder是款相对简单的静态分析工具,不进行数据流和控制流分析,甚至不识别函数的参数类型。
Flawfinder可将结果保存为格式化纯文本、HTML和CSV三种格式。
3款工具对比
- 检测能力:Cppcheck > TscanCode > Flawfinder
- 友好度:TscanCode > Cppcheck > Flawfinder
- 易用性:TscanCode > Cppcheck > Flawfinder
参考文献
- 向东, 刘海燕. C/C++静态代码安全检查工具研究[J]. 计算机工程与设计, 2005, 26(8):2110-2112.
- 罗琴灵. 基于静态检测的代码审计技术研究[J]. 2016.
- List of tools for static code analysis - Wikipedia
- C++代码质量扫描主流工具深度比较 - CSDN博客
- C/C++静态代码检查工具对比分析 - 网易博客
- Cppcheck 用法(上篇) - CSDN博客
- Cppcheck手册
- Flawfinder文档
2018年4月10日~16日 无锡
C/C++代码静态分析工具调研的更多相关文章
- 代码静态分析工具PC-LINT安装配置
代码静态分析工具PC-LINT安装配置--step by step 作者:ehui928 ...
- C++ 代码静态分析工具cppcheck【转】
转自:http://blog.csdn.net/chen19870707/article/details/42393217 权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] c ...
- 代码静态分析工具-splint的学习与使用[转]
代码静态分析工具--splint的学习与使用[转] 引言 最近在项目中使用了静态程序分析工具PC-Lint,体会到它在项目实施中带给开发人员的方便.PC-Lint是一款针对C/C++语言.window ...
- PHP代码静态分析工具PHPStan
最近发现自己写的PHP代码运行结果总跟自己预想的不一样,排查时发现大多是语法错误,在运行之前错误已经种下.可能是自己粗心大意,或者说php -l检测太简单,不过的确是有一些语法错误埋藏得太深(毕竟PH ...
- 代码静态分析工具--PMD,Findbugs,CheckStyle
最近学习Mybatis的官方文档,看到了[项目文档]一节有很多内容没有见过,做个笔记,理解一下. PMD 扫描Java源代码,查找潜在的问题,如: 可能的bugs,如空的try/catch/final ...
- 代码静态分析工具——splint的学习与使用
引言 最近在项目中使用了静态程序分析工具PC-Lint,体会到它在项目实施中带给开发人员的方便.PC-Lint是一款针对C/C++语言.windows平台的静态分析工具,FlexeLint是针对其他平 ...
- C++代码静态分析工具splint
1.引言 最近在项目中使用了静态程序分析工具PC-Lint, 体会到它在项目实施中带给开发人员的方便.PC-Lint是一款针对C/C++语言.windows平台的静态分析工具,FlexeLint是针对 ...
- PMD-Java代码静态分析工具使用
如今,使用代码分析工具来代替人工进行代码审查,已经是大势所趋了.用于Java代码检测的工具中,不乏许许多多的佼佼者,其中PMD就是其中一款.PMD既可以独立运行,也可以以命令行的形式运行,还可以作为插 ...
- 代码静态分析工具PCLint, Splint
一.PCLint REFER: 代码静态检查工具PC-Lint运用实践 二.Splint 1.在PC-Linux上安装 ①make error undefined reference toyywrap ...
随机推荐
- dt6.0之mip改造-img正则替换mip-img
最近没事,打算把自己的小项目改造为mip,进行测试学习,想把资讯栏目:http://zhimo.yuanzhumuban.cc/news/.全部改造为mip.但是MIP改造一项是:图片标签的改造.而且 ...
- 十二.Protobuf3编码
本文档描述了协议缓冲消息的二进制格式.在应用程序中使用Protocol Buffer不需要理解这一点,但是了解不同的Protocol Buffer格式如何影响编码消息的大小会非常有用. 一条简单的信息 ...
- matlab的diff()函数
diff():求差分 一阶差分 X = [1 1 2 3 5 8 13 21]; Y = diff(X) 结果: Y = 0 1 1 2 3 5 8 X = [1 1 1; 5 5 5; 25 25 ...
- HTML锚点控制,跳转页面后定位到相应位置
想在点击更多的页面 跳转后 用户能看到的是新闻 不用再用scollbar拖下来到新闻页面 这时候就需要在链接上 做下处理 <a href="/article/list/page/ ...
- Tensorflow细节-P196-输入数据处理框架
要点 1.filename_queue = tf.train.string_input_producer(files, shuffle=False)表示创建一个队列来维护列表 2.min_after_ ...
- P3604 美好的每一天
真·美好的每一天(美好个鬼啊) 真·调了一下午 原因是,我之前移动指针时没有先扩再缩,所以导致区间是负的:但是正常来说也没事,可是这题卡常,桶我开的是 unsigned short ,于是区间是负的, ...
- h5页面滑动卡顿解决方法
解决方式: 给滚动的元素加样式:-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling(允许独立的滚动区域和触摸回弹) 如果值为au ...
- 2017.10.3 国庆清北 D3T1 括号序列
题目描述 LYK有一个括号序列,但这个序列不一定合法. 一个合法的括号序列如下: ()是合法的括号序列. 若A是合法的括号序列,则(A)是合法的括号序列. 若A和B分别是合法的括号序列,则AB是合法的 ...
- python 路径引用问题
文件结构 入口文件· 将当前文件的父级,加入搜索目录里面 import sys import os current_dir = os.path.abspath(os.path.dirname(__fi ...
- 【概率论】5-10:二维正态分布(The Bivariate Normal Distributions)
title: [概率论]5-10:二维正态分布(The Bivariate Normal Distributions) categories: - Mathematic - Probability k ...