1

My target: detect all buffer access in C/C++ by using clang static checker.

My idea: use CheckPosition to get all memory read/write and then filter unrelated items.

My problem: However, I got stuck when I try to filter something like "int i = 1" "i++".

My solution: One way to filter this is to check whether the variable is pointer type or not by using isPointerType().

My question: But I need to get QualType first. The question is how? Or, do I have other ways to achieve my target???

My Clang Checker Code is as below:

#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");
}

The test result is as below:

    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
}

Here are some unsatisfied test results selected:

int type variable should be filtered

/home/chaz/playground/ep2AED/Kmp.c:27:13: warning: checkLocation: read buffer
            i++;

return expression should be filtered

/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
}

This arises twice

/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++;
        ^~~~~~~~~~

BTW, the test code is here: https://github.com/lucascapalbo/ep2AED

the test command is here:

clang-3.4 -Xclang -load -Xclang ~/bufferaccesschecker/checker.so -Xclang -analyzer-checker=alpha.core.BufferAccessChecker  -Xclang -analyze -w -c ~/playground/ep2AED/Kmp.c
chaz
  • 11
  • 1

1 Answers1

0

The problem was solved with the help of Artem Dergachev. Super thanks to him.

The solution idea is as below:

(1) dump the stmt by Stmt.dump() and you can see the ast tree

(2) according to the ast tree, you can dyn_cast stmt into different expr type. And then you can get QualType by expr.getType(). Then, we can filter the pointer type by isAnyPointerType()

Clang is not that hard but may be confusing to beginners (especially for me)

What you should do is to read those mateial carefully.

https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf
http://clang-analyzer.llvm.org/checker_dev_manual.html

When you begin to code the checker, you can always check different and confusing classes here rather than read the source code.

https://clang.llvm.org/doxygen/

Hope this helps!

chaz
  • 11
  • 1