Как определить весь доступ к буферу с помощью Clang Static Checker - PullRequest
0 голосов
/ 03 октября 2018

Моя цель: обнаружение всего доступа к буферу в C / C ++ с помощью статической проверки clang.

Моя идея: использовать CheckPosition, чтобы получить всю память для чтения / записиа затем отфильтровать несвязанные элементы.

Моя проблема: Однако я застрял, когда пытался отфильтровать что-то вроде "int i = 1" "i ++".

Мое решение: Один из способов отфильтровать это - проверить, относится ли переменная к типу указателя, с помощью isPointerType ().

Мой вопрос: Но мне нужно сначала получить QualType.Вопрос в том, как?Или у меня есть другие способы достижения моей цели ???

Мой код проверки лягушки такой, как показано ниже:

#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

1 Ответ

0 голосов
/ 05 октября 2018

Проблема была решена с помощью Артема Дергачева.Супер, спасибо ему.

Идея решения такова:

(1) сбросьте stmt на Stmt.dump(), и вы сможете увидеть дерево ast

(2)в соответствии с деревом ast, вы можете использовать dyn_cast stmt в другом типе expr.И тогда вы можете получить QualType с помощью expr.getType ().Затем мы можем отфильтровать тип указателя с помощью isAnyPointerType ()

Clang не так сложен, но может ввести в заблуждение новичков (особенно для меня)

Что вам нужно сделать, это внимательно прочитать эти материалы.

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

Когда вы начинаете кодировать средство проверки, вы всегда можете проверять различные и запутанные классы, а не читать исходный код.

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

Надеюсь, это поможет!

...