我的目标: 使用 clang 静态检查器检测 C/C++ 中的所有缓冲区访问。
我的想法:使用 CheckPosition 让所有内存读/写,然后过滤不相关的项目。
我的问题:但是,当我尝试过滤诸如“int i = 1”“i++”之类的内容时,我被卡住了。
我的解决方案: 过滤此问题的一种方法是使用 isPointerType() 检查变量是否为指针类型。
我的问题: 但我需要先获得 QualType。问题是如何?或者,我还有其他方法可以实现我的目标吗???
我的 Clang 检查器代码如下:
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "llvm-3.4/llvm/Support/raw_ostream.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
using namespace clang;
using namespace ento;
namespace {
class BufferAccessChecker : public Checker<check :: Location> {
//mutable std::unique_ptr<BuiltinBug> BT_access;
mutable std::unique_ptr<BugType> bugType;
public:
BufferAccessChecker(void) {
this->bugType.reset(new BugType("buffer access", "chaz analyzer"));
}
void checkLocation(SVal location, bool isLoad, const Stmt* S, CheckerContext &C) const;
};
}
void BufferAccessChecker::checkLocation(SVal location, bool isLoad, const Stmt* S, CheckerContext &C) const {
if (location.isUndef() || !location.getAs<Loc>())
return;
const MemRegion *R = location.getAsRegion();
if(!R)
return;
// if (location.getBaseKind() != SVal::LocKind)
// return;
// if (location.getSubKind() != loc::MemRegionKind)
// return;
// const ElementRegion *ER = dyn_cast<ElementRegion>(R);
// if(!ER)
// return;
ProgramStateRef state = C.getState();
ProgramStateRef notNullState, nullState;
std::tie(notNullState, nullState) = state->assume(L);
//filter some null states
if(isLoad){
if(!nullState && notNullState){
if(1){
ExplodedNode *loc = C.addTransition();
BugReport *bug = new BugReport(*this->bugType,
"checkLocation: read buffer", loc);
C.emitReport(bug);
}
}
return;
}else{
if(!nullState && notNullState){
ExplodedNode *loc = C.addTransition();
BugReport *bug = new BugReport(*this->bugType,
"checkLocation: write buffer", loc);
C.emitReport(bug);
}
}
}
extern "C"
const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING;
extern "C"
void clang_registerCheckers(CheckerRegistry ®istry) {
registry.addChecker <BufferAccessChecker>("alpha.core.BufferAccessChecker", "Checks buffer read/write");
}
测试结果如下:
clang-3.4 -Xclang -load -Xclang ~/bufferaccesschecker/checker.so -Xclang -analyzer-checker=alpha.core.BufferAccessChecker -Xclang -analyze -w -c ~/playground/ep2AED/Kmp.c
/home/chaz/playground/ep2AED/Kmp.c:17:14: warning: checkLocation: write buffer
falha[0] = 0;
~~~~~~~~~^~~
/home/chaz/playground/ep2AED/Kmp.c:18:12: warning: checkLocation: read buffer
while (i<tamanhoPadrao) {
^
/home/chaz/playground/ep2AED/Kmp.c:19:18: warning: checkLocation: read buffer
if (p[i] == p[j]) {
~~~~~^~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:20:21: warning: checkLocation: write buffer
falha[i]= j+1;
~~~~~~~~^~~~~
/home/chaz/playground/ep2AED/Kmp.c:26:21: warning: checkLocation: write buffer
falha[i]=0;
~~~~~~~~^~
/home/chaz/playground/ep2AED/Kmp.c:26:22: warning: checkLocation: read buffer
falha[i]=0;
^
/home/chaz/playground/ep2AED/Kmp.c:27:13: warning: checkLocation: read buffer
i++;
^~~
/home/chaz/playground/ep2AED/Kmp.c:36:18: warning: checkLocation: read buffer
int* falha = funcaoDeFalha(p);
^~~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:38:13: warning: checkLocation: read buffer
while (*i < tamanhoTexto) {
^
/home/chaz/playground/ep2AED/Kmp.c:38:15: warning: checkLocation: read buffer
while (*i < tamanhoTexto) {
~~~^~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:38:17: warning: checkLocation: read buffer
while (*i < tamanhoTexto) {
^~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:39:9: warning: checkLocation: read buffer
if(texto[*i] == p[*j]){ //match
^~
/home/chaz/playground/ep2AED/Kmp.c:39:12: warning: checkLocation: read buffer
if(texto[*i] == p[*j]){ //match
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:39:19: warning: checkLocation: read buffer
if(texto[*i] == p[*j]){ //match
^
/home/chaz/playground/ep2AED/Kmp.c:39:22: warning: checkLocation: read buffer
if(texto[*i] == p[*j]){ //match
~~~~~~~~~~^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:39:28: warning: checkLocation: read buffer
if(texto[*i] == p[*j]){ //match
^
/home/chaz/playground/ep2AED/Kmp.c:40:17: warning: checkLocation: read buffer
if(*j == tamanhoPadrao - 1){
^
/home/chaz/playground/ep2AED/Kmp.c:40:22: warning: checkLocation: read buffer
if(*j == tamanhoPadrao - 1){
^~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:41:26: warning: checkLocation: read buffer
return (*i-*j);
^
/home/chaz/playground/ep2AED/Kmp.c:43:17: warning: checkLocation: read buffer
(*i)++;
^~~~~~
/home/chaz/playground/ep2AED/Kmp.c:43:19: warning: checkLocation: read buffer
(*i)++;
^
/home/chaz/playground/ep2AED/Kmp.c:44:17: warning: checkLocation: read buffer
(*j)++;
^~~~~~
/home/chaz/playground/ep2AED/Kmp.c:44:19: warning: checkLocation: read buffer
(*j)++;
^
/home/chaz/playground/ep2AED/Kmp.c:48:17: warning: checkLocation: read buffer
if(*j>0){
^
/home/chaz/playground/ep2AED/Kmp.c:49:22: warning: checkLocation: read buffer
(*j) = falha[*j-1];
~~~~~^~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:49:31: warning: checkLocation: read buffer
(*j) = falha[*j-1];
^
/home/chaz/playground/ep2AED/Kmp.c:51:17: warning: checkLocation: read buffer
(*i)++;
^~~~~~
/home/chaz/playground/ep2AED/Kmp.c:51:19: warning: checkLocation: read buffer
(*i)++;
^
/home/chaz/playground/ep2AED/Kmp.c:55:13: warning: checkLocation: read buffer
return -1;
^
/home/chaz/playground/ep2AED/Kmp.c:56:1: warning: checkLocation: read buffer
}
^
/home/chaz/playground/ep2AED/Kmp.c:65:5: warning: checkLocation: read buffer
int i = KMPMatch(texto, p, &iKmp, &jKmp);
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:65:33: warning: checkPreStmt: buffer access
int i = KMPMatch(texto, p, &iKmp, &jKmp);
^~~~
/home/chaz/playground/ep2AED/Kmp.c:65:40: warning: checkPreStmt: buffer access
int i = KMPMatch(texto, p, &iKmp, &jKmp);
^~~~
/home/chaz/playground/ep2AED/Kmp.c:66:5: warning: checkLocation: read buffer
if(texto[strlen(p)] == ' '){
^~
/home/chaz/playground/ep2AED/Kmp.c:66:8: warning: checkLocation: read buffer
if(texto[strlen(p)] == ' '){
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:67:21: warning: checkLocation: write buffer
resposta[0] = i;
~~~~~~~~~~~~^~~
/home/chaz/playground/ep2AED/Kmp.c:67:23: warning: checkLocation: read buffer
resposta[0] = i;
^
/home/chaz/playground/ep2AED/Kmp.c:68:9: warning: checkLocation: read buffer
iterador++;
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:68:9: warning: checkLocation: read buffer
iterador++;
^~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:71:21: warning: checkLocation: write buffer
resposta[0] = -1;
~~~~~~~~~~~~^~~~
/home/chaz/playground/ep2AED/Kmp.c:72:9: warning: checkLocation: read buffer
iterador++;
^~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:74:5: warning: checkLocation: read buffer
while (i < strlen(texto) && i != -1){
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:74:12: warning: checkLocation: read buffer
while (i < strlen(texto) && i != -1){
^
/home/chaz/playground/ep2AED/Kmp.c:74:14: warning: checkLocation: read buffer
while (i < strlen(texto) && i != -1){
~~^~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:74:16: warning: checkLocation: read buffer
while (i < strlen(texto) && i != -1){
^~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:74:23: warning: checkLocation: read buffer
while (i < strlen(texto) && i != -1){
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:74:30: warning: checkLocation: read buffer
while (i < strlen(texto) && i != -1){
~~~~~~~~~~~~~~~~~~^~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:74:33: warning: checkLocation: read buffer
while (i < strlen(texto) && i != -1){
^
/home/chaz/playground/ep2AED/Kmp.c:75:9: warning: checkLocation: read buffer
i = KMPMatch(texto, p , &iKmp,&jKmp);
^
/home/chaz/playground/ep2AED/Kmp.c:75:11: warning: checkLocation: read buffer
i = KMPMatch(texto, p , &iKmp,&jKmp);
~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:75:13: warning: checkLocation: read buffer
i = KMPMatch(texto, p , &iKmp,&jKmp);
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:75:22: warning: checkLocation: read buffer
i = KMPMatch(texto, p , &iKmp,&jKmp);
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:75:34: warning: checkLocation: read buffer
i = KMPMatch(texto, p , &iKmp,&jKmp);
^~~~
/home/chaz/playground/ep2AED/Kmp.c:75:34: warning: checkPreStmt: buffer access
i = KMPMatch(texto, p , &iKmp,&jKmp);
^~~~
/home/chaz/playground/ep2AED/Kmp.c:75:40: warning: checkLocation: read buffer
i = KMPMatch(texto, p , &iKmp,&jKmp);
^~~~
/home/chaz/playground/ep2AED/Kmp.c:75:40: warning: checkPreStmt: buffer access
i = KMPMatch(texto, p , &iKmp,&jKmp);
^~~~
/home/chaz/playground/ep2AED/Kmp.c:76:9: warning: checkLocation: read buffer
if(texto[i-1] == ' '){
^~
/home/chaz/playground/ep2AED/Kmp.c:76:12: warning: checkLocation: read buffer
if(texto[i-1] == ' '){
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:76:18: warning: checkLocation: read buffer
if(texto[i-1] == ' '){
^
/home/chaz/playground/ep2AED/Kmp.c:78:32: warning: checkLocation: read buffer
resposta[iterador] = i;
~~~~~~~~~~~~~~~~~~~^~~
/home/chaz/playground/ep2AED/Kmp.c:78:32: warning: checkLocation: write buffer
resposta[iterador] = i;
~~~~~~~~~~~~~~~~~~~^~~
/home/chaz/playground/ep2AED/Kmp.c:79:13: warning: checkLocation: read buffer
iterador++;
^~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:82:6: warning: checkLocation: read buffer
*controle = iterador;
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:82:15: warning: checkLocation: read buffer
*controle = iterador;
~~~~~~~~~~^~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:82:17: warning: checkLocation: read buffer
*controle = iterador;
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:83:5: warning: checkLocation: read buffer
return resposta;
^~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:83:12: warning: checkLocation: read buffer
return resposta;
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:84:1: warning: checkLocation: read buffer
}
^
/home/chaz/playground/ep2AED/Kmp.c:92:15: warning: checkLocation: read buffer
while(i < *controle){
^
/home/chaz/playground/ep2AED/Kmp.c:92:20: warning: checkLocation: read buffer
while(i < *controle){
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:93:16: warning: checkLocation: read buffer
if(resposta[0] == -1)//nao existe a palavra
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:93:16: warning: checkLocation: read buffer
if(resposta[0] == -1)//nao existe a palavra
^~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:94:39: warning: checkLocation: read buffer
printf("%d", resposta[0]);
^
/home/chaz/playground/ep2AED/Kmp.c:95:37: warning: checkLocation: read buffer
else if(resposta[i] != -1){
^~
/home/chaz/playground/ep2AED/Kmp.c:96:40: warning: checkLocation: read buffer
printf("%d ", resposta[i]);
^
/home/chaz/playground/ep2AED/Kmp.c:98:13: warning: checkLocation: read buffer
i++;
^~~
/home/chaz/playground/ep2AED/Kmp.c:99:10: warning: checkLocation: read buffer
}printf("\n");
^~~~~~
/home/chaz/playground/ep2AED/Kmp.c:102:9: warning: checkLocation: read buffer
while(palavras) {
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:102:15: warning: checkLocation: read buffer
while(palavras) {
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:104:13: warning: checkLocation: read buffer
int *resposta = ChamaKMP(texto, palavras,numeroDePadroes, controle);
^~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:104:29: warning: checkLocation: read buffer
int *resposta = ChamaKMP(texto, palavras,numeroDePadroes, controle);
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:104:29: warning: checkLocation: read buffer
int *resposta = ChamaKMP(texto, palavras,numeroDePadroes, controle);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:104:38: warning: checkLocation: read buffer
int *resposta = ChamaKMP(texto, palavras,numeroDePadroes, controle);
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:104:45: warning: checkLocation: read buffer
int *resposta = ChamaKMP(texto, palavras,numeroDePadroes, controle);
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:104:54: warning: checkLocation: read buffer
int *resposta = ChamaKMP(texto, palavras,numeroDePadroes, controle);
^~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:104:71: warning: checkLocation: read buffer
int *resposta = ChamaKMP(texto, palavras,numeroDePadroes, controle);
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:105:13: warning: checkLocation: read buffer
while(i < *controle){
^~~~~
/home/chaz/playground/ep2AED/Kmp.c:105:19: warning: checkLocation: read buffer
while(i < *controle){
^
/home/chaz/playground/ep2AED/Kmp.c:105:24: warning: checkLocation: read buffer
while(i < *controle){
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:106:17: warning: checkLocation: read buffer
if(resposta[0] == -1)//nao existe a palavra
^~
/home/chaz/playground/ep2AED/Kmp.c:106:20: warning: checkLocation: read buffer
if(resposta[0] == -1)//nao existe a palavra
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:106:32: warning: checkLocation: read buffer
if(resposta[0] == -1)//nao existe a palavra
~~~~~~~~~~~~^~~~~
/home/chaz/playground/ep2AED/Kmp.c:107:21: warning: checkLocation: read buffer
printf("%d", resposta[0]);
^~~~~~
/home/chaz/playground/ep2AED/Kmp.c:107:21: warning: checkLocation: read buffer
printf("%d", resposta[0]);
^~~~~~~~~~~~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:107:34: warning: checkLocation: read buffer
printf("%d", resposta[0]);
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:108:25: warning: checkLocation: read buffer
else if(resposta[i] != -1){
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:108:34: warning: checkLocation: read buffer
else if(resposta[i] != -1){
^
/home/chaz/playground/ep2AED/Kmp.c:108:37: warning: checkLocation: read buffer
else if(resposta[i] != -1){
~~~~~~~~~~~~^~~~~
/home/chaz/playground/ep2AED/Kmp.c:109:21: warning: checkLocation: read buffer
printf("%d ", resposta[i]);
^~~~~~
/home/chaz/playground/ep2AED/Kmp.c:109:21: warning: checkLocation: read buffer
printf("%d ", resposta[i]);
^~~~~~~~~~~~~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:109:35: warning: checkLocation: read buffer
printf("%d ", resposta[i]);
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:109:44: warning: checkLocation: read buffer
printf("%d ", resposta[i]);
^
/home/chaz/playground/ep2AED/Kmp.c:111:17: warning: checkLocation: read buffer
i++;
^
/home/chaz/playground/ep2AED/Kmp.c:111:17: warning: checkLocation: read buffer
i++;
^~~
/home/chaz/playground/ep2AED/Kmp.c:112:14: warning: checkLocation: read buffer
}printf("\n");
^~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:112:21: warning: checkLocation: read buffer
}printf("\n");
^~~~
/home/chaz/playground/ep2AED/Kmp.c:113:13: warning: checkLocation: read buffer
i = 0;
^
/home/chaz/playground/ep2AED/Kmp.c:113:15: warning: checkLocation: read buffer
i = 0;
~~^~~
/home/chaz/playground/ep2AED/Kmp.c:114:22: warning: checkLocation: read buffer
palavras = strtok(NULL, " ");
~~~~~~~~~^~~~~~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:114:24: warning: checkLocation: read buffer
palavras = strtok(NULL, " ");
^~~~~~~~~~~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:117:1: warning: checkLocation: read buffer
}
以下是选择的一些不满意的测试结果:
应过滤 int 类型变量
/home/chaz/playground/ep2AED/Kmp.c:27:13: warning: checkLocation: read buffer
i++;
返回表达式应该被过滤
/home/chaz/playground/ep2AED/Kmp.c:55:13: warning: checkLocation: read buffer
return -1;
/home/chaz/playground/ep2AED/Kmp.c:56:1: warning: checkLocation: read buffer
}
这出现了两次
/home/chaz/playground/ep2AED/Kmp.c:68:9: warning: checkLocation: read buffer
iterador++;
^~~~~~~~
/home/chaz/playground/ep2AED/Kmp.c:68:9: warning: checkLocation: read buffer
iterador++;
^~~~~~~~~~
顺便说一句,测试代码在这里: https ://github.com/lucascapalbo/ep2AED
测试命令在这里:
clang-3.4 -Xclang -load -Xclang ~/bufferaccesschecker/checker.so -Xclang -analyzer-checker=alpha.core.BufferAccessChecker -Xclang -analyze -w -c ~/playground/ep2AED/Kmp.c