C/C++代碼靜態分析工具調研

C/C++代碼靜態分析工具調研

摘自:https://www.jianshu.com/p/92886d979401

簡述

靜態分析(static analysis)是指在不執行代碼的狀況下對其進行分析評估的過程,是軟件質量和軟件安全保障的重要一環。它經過詞法分析、語義分析、控制流分析、數據流分析等技術對代碼逐行解析暴露問題,從而協助咱們將許多在運行時纔會暴露的棘手麻煩扼殺於搖籃之中。php

典型問題示例

代碼靜態分析可以識別諸多類型的漏洞或缺陷,輕至警告級的「變量未使用」,重至錯誤級的各種bug,這裏列舉幾種常見的、較嚴重的、可靜態檢測的問題。html

■ 緩衝區溢出

緩衝區溢出是指向緩衝區中存入超出其空間大小的數據量,致使多餘的數據覆蓋其餘區域的合法數據,相似倒入容器中的水過多而致使溢出,流到它不應去的地方,形成不可預期的後果。從實踐統計看,緩衝區溢出問題是軟件中最廣泛存在的漏洞問題,在C/C++這類不提供內存越界檢測的語言中尤甚。一般,發生緩衝區溢出的狀況有:python

  • 字符串拷貝,當目標緩衝區長度小於源字串的長度時(此類的函數包括strcpy_mbscpystrcatwcscatmemcpystrncpy_mbsncpystrncatwcsncat等)。
// 字符串拷貝以前沒有對s作長度判斷,若是超過10,就會形成緩衝區溢出。 void func(char* s) { char buf[10]; strcpy(buf, s); } 
  • 格式化字符串處理,當參數與格式化字符串不匹配時(此類的函數包括printffprintfsprintfswprintf等)。
// %n將前面打印的字串長度信息寫到相應地址 int len = 0; printf("This is a test string.%n", &len); 
// 錯誤的寫法,此時長度信息會寫到地址爲0的內存空間中 int len = 0; printf("This is a test string.%n", len); 
  • 字符串讀取,當緩衝區小於所要讀入的字符串長度時(此類的函數包括scanffscanfsscanfgetsgetcfgetsfgetc等)。
// 用戶輸入的字串長度不受控制,若是超過10,就會形成緩衝區溢出。 char buf[10]; scanf("%s", &buf); 

■ 內存泄漏

內存泄漏通常指堆內存的泄漏(也有系統資源的泄漏),程序申請的內存資源沒有被合理地釋放,致使這部份內存不能被回收利用而形成資源的浪費。嚴重時,過多的內存泄漏會形成系統崩潰。C/C++語言沒有自動回收機制,須要程序員自行確保內存使用的閉環(new/deletealloc/freemalloc/freeGlobalAlloc/GlobalFree成對使用)。git

 
 

一般,發生內存泄漏的狀況有:程序員

  • 分配內存後忘了調用相應的釋放函數。
  • 過程因達到某種條件提早結束,未能執行後面的內存釋放函數。
  • 程序設計不合理,不斷分配內存,到最後才一塊兒釋放,雖然總體上不算內存泄漏,但在過程當中已經醞釀了資源耗盡的可能性,無異於內存泄漏。

■ 野指針

當指針變量未被初始化,或指向的內存已被回收時,該指針便成了野指針。其指向的內存地址是非法的,對這塊非法區域進行操做將致使不可預料的後果。github

// 對指針是否爲空的判斷看是嚴謹,實際上是無效的。 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——進行詳細調研:windows

  • 語言:支持C/C++代碼分析
  • 平臺:支持在Windows和/或Linux平臺運行
  • 受權:免費

爲進行一次實踐對比,從TscanCode的GitHub上抓到一組現成的C/C++編碼問題示例,共94個CPP文件,考察三者的檢測效果。安全

運行平臺:Windows
被測語言:C/C++
測試集:TscanCode/samples/cppbash

■ 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)跟着嚮導「下一步」便可。

 
Cppcheck有GUI,選擇菜單欄「Analyze」下的「文件」或「目錄」便可對源代碼進行靜態分析。
 
運行結果對94個例子的分析十分到位,只不過底側的代碼預覽對中文註釋彷佛不太友好。

除了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)跟着嚮導「下一步」便可。

 
一樣具備用戶友好的GUI,且UI設計更時尚些。點擊「掃描文件夾」或「掃描文件」選定路徑後點擊「開始掃描」便可使用。
 
掃描結果,對中文註釋必然友好。

TscanCode的提示信息能夠說直接照搬了Cppcheck,但給出的提示數量明顯少於Cppcheck,以mismatchsize.cpp爲例:

void Demo() { //分配的內存空間不匹配 int i = malloc(3); } 
 
Cppcheck對mismatchsize.cpp的檢測結果有4條提示,TscanCode相應地只給出了後兩條。

■ 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格式後方可正常運行:

 
94個示例,僅檢測出11個問題。

David A. Wheeler本人也在官網特別聲明Flawfinder是款相對簡單的靜態分析工具,不進行數據流和控制流分析,甚至不識別函數的參數類型。

Flawfinder可將結果保存爲格式化純文本HTMLCSV三種格式。

3款工具對比

  • 檢測能力:Cppcheck > TscanCode > Flawfinder
  • 友好度:TscanCode > Cppcheck > Flawfinder
  • 易用性:TscanCode > Cppcheck > Flawfinder

參考文獻

2018年4月10日~16日 無錫

相關文章
相關標籤/搜索