added and integrated checkautovariables that gscacco created
This commit is contained in:
parent
3fab99a5cb
commit
33df121567
9
Makefile
9
Makefile
|
@ -5,7 +5,8 @@ BIN=${DESTDIR}/usr/bin
|
|||
|
||||
###### Object Files
|
||||
|
||||
OBJECTS = src/checkbufferoverrun.o \
|
||||
OBJECTS = src/checkautovariables.o \
|
||||
src/checkbufferoverrun.o \
|
||||
src/checkclass.o \
|
||||
src/checkdangerousfunctions.o \
|
||||
src/checkfunctionusage.o \
|
||||
|
@ -49,6 +50,7 @@ TESTOBJ = test/testbufferoverrun.o \
|
|||
test/testtokenize.o \
|
||||
test/testunusedprivfunc.o \
|
||||
test/testunusedvar.o \
|
||||
src/checkautovariables.o \
|
||||
src/checkbufferoverrun.o \
|
||||
src/checkclass.o \
|
||||
src/checkdangerousfunctions.o \
|
||||
|
@ -100,6 +102,9 @@ install: cppcheck
|
|||
|
||||
###### Build
|
||||
|
||||
src/checkautovariables.o: src/checkautovariables.cpp src/checkautovariables.h src/check.h src/settings.h src/token.h src/tokenize.h src/errorlogger.h
|
||||
$(CXX) $(CXXFLAGS) -c -o src/checkautovariables.o src/checkautovariables.cpp
|
||||
|
||||
src/checkbufferoverrun.o: src/checkbufferoverrun.cpp src/checkbufferoverrun.h src/settings.h src/tokenize.h src/errorlogger.h src/token.h
|
||||
$(CXX) $(CXXFLAGS) -c -o src/checkbufferoverrun.o src/checkbufferoverrun.cpp
|
||||
|
||||
|
@ -127,7 +132,7 @@ src/checksecurity.o: src/checksecurity.cpp src/checksecurity.h src/errorlogger.h
|
|||
src/checkstl.o: src/checkstl.cpp src/checkstl.h src/check.h src/settings.h src/tokenize.h src/errorlogger.h src/token.h
|
||||
$(CXX) $(CXXFLAGS) -c -o src/checkstl.o src/checkstl.cpp
|
||||
|
||||
src/cppcheck.o: src/cppcheck.cpp src/cppcheck.h src/settings.h src/errorlogger.h src/checkfunctionusage.h src/tokenize.h src/token.h src/preprocessor.h src/checkmemoryleak.h src/checkbufferoverrun.h src/checkdangerousfunctions.h src/checkclass.h src/checkheaders.h src/checkother.h src/filelister.h
|
||||
src/cppcheck.o: src/cppcheck.cpp src/cppcheck.h src/settings.h src/errorlogger.h src/checkfunctionusage.h src/tokenize.h src/token.h src/preprocessor.h src/checkmemoryleak.h src/checkbufferoverrun.h src/checkdangerousfunctions.h src/checkclass.h src/checkheaders.h src/checkother.h src/filelister.h src/check.h
|
||||
$(CXX) $(CXXFLAGS) -c -o src/cppcheck.o src/cppcheck.cpp
|
||||
|
||||
src/cppcheckexecutor.o: src/cppcheckexecutor.cpp src/cppcheckexecutor.h src/errorlogger.h src/settings.h src/cppcheck.h src/checkfunctionusage.h src/tokenize.h src/token.h src/threadexecutor.h
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2009 Daniel Marjamäki, Reijo Tomperi, Nicolas Le Cam,
|
||||
* Leandro Penz, Kimmo Varis, Vesa Pikki
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Buffer overrun..
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "checkautovariables.h"
|
||||
#include "tokenize.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <list>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <cstdlib> // <- strtoul
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Register this check class into cppcheck by creating a static instance of it..
|
||||
namespace
|
||||
{
|
||||
static CheckAutoVariables instance;
|
||||
}
|
||||
|
||||
|
||||
// _callStack used when parsing into subfunctions.
|
||||
|
||||
|
||||
bool CheckAutoVariables::error_av(const Token* left, const Token* right)
|
||||
{
|
||||
std::string left_var = left->str();
|
||||
std::string right_var = right->str();
|
||||
std::list<std::string>::iterator it_fp;
|
||||
|
||||
for (it_fp = fp_list.begin();it_fp != fp_list.end();it_fp++)
|
||||
{
|
||||
std::string vname = (*it_fp);
|
||||
//cout << "error_av " << vname << " " << left_var << endl;
|
||||
if (vname == left_var)
|
||||
{
|
||||
//cout << "Beccato" << endl;
|
||||
break; //The left argument is a formal parameter
|
||||
}
|
||||
|
||||
}
|
||||
if (it_fp == fp_list.end())
|
||||
return false; //The left argument is NOT a formal parameter
|
||||
|
||||
std::list<std::string>::iterator id_vd;
|
||||
for (id_vd = vd_list.begin();id_vd != vd_list.end();id_vd++)
|
||||
{
|
||||
std::string vname = (*id_vd);
|
||||
if (vname == right_var)
|
||||
break; //The left argument is a variable declaration
|
||||
}
|
||||
if (id_vd == vd_list.end())
|
||||
return false; //The left argument is NOT a variable declaration
|
||||
//If I reach this point there is a wrong assignement of an auto-variable to an effective parameter of a function
|
||||
return true;
|
||||
|
||||
}
|
||||
bool CheckAutoVariables::is_auto_var(const Token* t)
|
||||
{
|
||||
std::list<std::string>::iterator id_vd;
|
||||
std::string v = t->str();
|
||||
for (id_vd = vd_list.begin();id_vd != vd_list.end();id_vd++)
|
||||
{
|
||||
std::string vname = (*id_vd);
|
||||
if (vname == v)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void print(const Token *tok, int num)
|
||||
{
|
||||
const Token *t = tok;
|
||||
std::cout << tok->linenr() << " PRINT ";
|
||||
for (int i = 0;i < num;i++)
|
||||
{
|
||||
std::cout << " [" << t->str() << "] ";
|
||||
t = t->next();
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
bool isTypeName(const Token *tok)
|
||||
{
|
||||
bool ret = false;
|
||||
std::string _str = tok->str();
|
||||
const char *type[] = {"case", "return", "delete", 0};
|
||||
for (int i = 0; type[i]; i++)
|
||||
ret |= (_str == type[i]);
|
||||
return !ret;
|
||||
}
|
||||
void CheckAutoVariables::addVD(const Token* tok)
|
||||
{
|
||||
std::string var_name;
|
||||
var_name = tok->str();
|
||||
//cout << "VD " << tok->linenr() << " " << var_name << endl;
|
||||
vd_list.push_back(var_name);
|
||||
}
|
||||
void CheckAutoVariables::autoVariables()
|
||||
{
|
||||
bool begin_function = false;
|
||||
bool begin_function_decl = false;
|
||||
int bindent = 0;
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
|
||||
if (Token::Match(tok, "%type% %var% (") ||
|
||||
Token::Match(tok, "%type% * %var% (") ||
|
||||
Token::Match(tok, "%type% :: %var% ("))
|
||||
{
|
||||
begin_function = true;
|
||||
fp_list.clear();
|
||||
vd_list.clear();
|
||||
}
|
||||
else if (begin_function && begin_function_decl && Token::Match(tok, "%type% * %var%"))
|
||||
{
|
||||
std::string var_name;
|
||||
|
||||
var_name = tok->tokAt(2)->str();
|
||||
//cout << "FP " << tok->linenr() << " " << var_name << endl;
|
||||
fp_list.push_back(var_name);
|
||||
}
|
||||
else if (begin_function && Token::Match(tok, "("))
|
||||
begin_function_decl = true;
|
||||
else if (begin_function && Token::Match(tok, ")"))
|
||||
{
|
||||
begin_function_decl = false;
|
||||
}
|
||||
else if (begin_function && Token::Match(tok, "{"))
|
||||
bindent++;
|
||||
else if (begin_function && Token::Match(tok, "}"))
|
||||
{
|
||||
bindent--;
|
||||
}
|
||||
else if (bindent > 0 && Token::Match(tok, "%type% :: %any%")) //Inside a function
|
||||
{
|
||||
std::string var_name;
|
||||
//print(tok,5);
|
||||
var_name = tok->tokAt(2)->str();
|
||||
vd_list.push_back(var_name);
|
||||
}
|
||||
else if (bindent > 0 && Token::Match(tok, "%var% %var% ;")) //Inside a function
|
||||
{
|
||||
if (!isTypeName(tok))
|
||||
continue;
|
||||
addVD(tok->tokAt(1));
|
||||
}
|
||||
else if (bindent > 0 && Token::Match(tok, "const %var% %var% ;")) //Inside a function
|
||||
{
|
||||
if (!isTypeName(tok->tokAt(1)))
|
||||
continue;
|
||||
addVD(tok->tokAt(2));
|
||||
}
|
||||
else if (bindent > 0 && Token::Match(tok, "%var% = & %var%")) //Critical assignement
|
||||
{
|
||||
if (error_av(tok->tokAt(0), tok->tokAt(3)))
|
||||
_errorLogger->genericError(_tokenizer,
|
||||
tok,
|
||||
"Wrong assignement of an auto-variable to an effective parameter of a function");
|
||||
}
|
||||
else if (bindent > 0 && Token::Match(tok, "%var% [ %any% ] = & %var%")) //Critical assignement
|
||||
{
|
||||
if (error_av(tok->tokAt(0), tok->tokAt(6)))
|
||||
_errorLogger->genericError(_tokenizer,
|
||||
tok,
|
||||
"Wrong assignement of an auto-variable to an effective parameter of a function");
|
||||
}
|
||||
else if (bindent > 0 && Token::Match(tok, "return & %var%")) //Critical return
|
||||
{
|
||||
if (is_auto_var(tok->tokAt(2)))
|
||||
_errorLogger->genericError(_tokenizer,
|
||||
tok,
|
||||
"Return of the address of an auto-variable");
|
||||
}
|
||||
}
|
||||
vd_list.clear();
|
||||
fp_list.clear();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2009 Daniel Marjamäki, Reijo Tomperi, Nicolas Le Cam,
|
||||
* Leandro Penz, Kimmo Varis, Vesa Pikki
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||
*/
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#ifndef CheckAutoVariablesH
|
||||
#define CheckAutoVariablesH
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "check.h"
|
||||
#include "token.h"
|
||||
#include <list>
|
||||
|
||||
class CheckAutoVariables : public Check
|
||||
{
|
||||
public:
|
||||
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
{
|
||||
_tokenizer = tokenizer;
|
||||
_settings = settings;
|
||||
_errorLogger = errorLogger;
|
||||
autoVariables();
|
||||
}
|
||||
|
||||
/** Check for buffer overruns */
|
||||
void autoVariables();
|
||||
private:
|
||||
std::list<std::string> fp_list;
|
||||
std::list<std::string> vd_list;
|
||||
bool error_av(const Token* left, const Token* right);
|
||||
bool is_auto_var(const Token* t);
|
||||
void addVD(const Token* t);
|
||||
const Tokenizer *_tokenizer;
|
||||
const Settings *_settings;
|
||||
ErrorLogger *_errorLogger;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
|
@ -95,6 +95,15 @@ public:
|
|||
*/
|
||||
virtual void reportStatus(unsigned int index, unsigned int max) = 0;
|
||||
|
||||
void genericError(const Tokenizer *tokenizer, const Token *Location, const std::string &msg)
|
||||
{
|
||||
_writemsg(tokenizer, Location, "error", "" + msg + "", "genericError");
|
||||
}
|
||||
static bool genericError()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void arrayIndexOutOfBounds(const Tokenizer *tokenizer, const std::list<const Token *> &Location)
|
||||
{
|
||||
_writemsg(tokenizer, Location, "all", "Array index out of bounds", "arrayIndexOutOfBounds");
|
||||
|
|
|
@ -57,6 +57,9 @@ int main()
|
|||
// Error messages..
|
||||
std::list<Message> err;
|
||||
|
||||
// Generic error message
|
||||
err.push_back(Message("genericError", Message::error, "%1", "msg"));
|
||||
|
||||
// checkbufferoverrun.cpp
|
||||
err.push_back(Message("arrayIndexOutOfBounds", Message::all, "Array index out of bounds"));
|
||||
err.push_back(Message("bufferOverrun", Message::all, "Buffer overrun"));
|
||||
|
|
Loading…
Reference in New Issue