Moved stloutofbounds check to CheckStl class.

This commit is contained in:
Reijo Tomperi 2009-02-10 19:56:00 +00:00
parent e40c36a6bd
commit 4660b7648d
7 changed files with 115 additions and 110 deletions

View File

@ -555,73 +555,10 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
}
//---------------------------------------------------------------------------
void CheckBufferOverrunClass::STLSizeProblems()
{
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (!Token::simpleMatch(tok, "for ("))
continue;
int indent = 1;
tok = tok->tokAt(2);
const Token *num = 0;
const Token *var = 0;
while (tok)
{
if (tok->str() == "(")
++indent;
if (tok->str() == ")")
{
--indent;
if (indent == 0)
break;
}
if (Token::Match(tok, "; %var% <= %var% . size ( ) ;"))
{
num = tok->tokAt(1);
var = tok->tokAt(3);
}
tok = tok->next();
}
tok = tok->next();
if (!num || tok->str() != "{")
continue;
std::string pattern = var->str() + " [ " + num->str() + " ]";
while (tok)
{
if (tok->str() == "{")
++indent;
if (tok->str() == "}")
{
--indent;
if (indent == 0)
break;
}
if (Token::Match(tok, pattern.c_str()))
{
_errorLogger->stlOutOfBounds(_tokenizer, tok, "When " + num->str() + " == size(), " + pattern);
}
tok = tok->next();
}
}
}
void CheckBufferOverrunClass::bufferOverrun()
{
CheckBufferOverrun_LocalVariable();
CheckBufferOverrun_StructVariable();
STLSizeProblems();
}
//---------------------------------------------------------------------------

View File

@ -45,12 +45,6 @@ private:
/** Check for buffer overruns - this is the function that performs the actual checking */
void CheckBufferOverrun_CheckScope(const Token *tok, const char *varname[], const int size, const int total_size, unsigned int varid);
/**
* Finds errors like this:
* for (unsigned ii = 0; ii <= foo.size(); ++ii)
*/
void STLSizeProblems();
const Tokenizer *_tokenizer;
const Settings _settings;
ErrorLogger *_errorLogger;

View File

@ -47,3 +47,66 @@ void CheckStl::iterators()
}
}
}
void CheckStl::stlOutOfBounds()
{
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (!Token::simpleMatch(tok, "for ("))
continue;
int indent = 1;
tok = tok->tokAt(2);
const Token *num = 0;
const Token *var = 0;
while (tok)
{
if (tok->str() == "(")
++indent;
if (tok->str() == ")")
{
--indent;
if (indent == 0)
break;
}
if (Token::Match(tok, "; %var% <= %var% . size ( ) ;"))
{
num = tok->tokAt(1);
var = tok->tokAt(3);
}
tok = tok->next();
}
tok = tok->next();
if (!num || tok->str() != "{")
continue;
std::string pattern = var->str() + " [ " + num->str() + " ]";
while (tok)
{
if (tok->str() == "{")
++indent;
if (tok->str() == "}")
{
--indent;
if (indent == 0)
break;
}
if (Token::Match(tok, pattern.c_str()))
{
_errorLogger->stlOutOfBounds(_tokenizer, tok, "When " + num->str() + " == size(), " + pattern);
}
tok = tok->next();
}
}
}

View File

@ -32,6 +32,13 @@ public:
CheckStl(const Tokenizer *tokenizer, ErrorLogger *errorLogger);
~CheckStl();
/**
* Finds errors like this:
* for (unsigned ii = 0; ii <= foo.size(); ++ii)
*/
void stlOutOfBounds();
void iterators();
private:

View File

@ -412,6 +412,9 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
CheckStl checkStl(&_tokenizer, this);
if (ErrorLogger::iteratorUsage())
checkStl.iterators();
if (ErrorLogger::stlOutOfBounds())
checkStl.stlOutOfBounds();
}
Settings CppCheck::settings() const

View File

@ -93,8 +93,6 @@ private:
TEST_CASE(varid1);
TEST_CASE(varid2);
TEST_CASE(STLSize);
TEST_CASE(STLSizeNoErr);
}
@ -472,45 +470,6 @@ private:
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
}
void STLSize()
{
check("void foo()\n"
"{\n"
" std::vector<int> foo;\n"
" for (unsigned int ii = 0; ii <= foo.size(); ++ii)\n"
" {\n"
" foo[ii] = 0;\n"
" }\n"
"}\n");
ASSERT_EQUALS(std::string("[test.cpp:6]: (error) When ii == size(), foo [ ii ] is out of bounds\n"), errout.str());
}
void STLSizeNoErr()
{
{
check("void foo()\n"
"{\n"
" std::vector<int> foo;\n"
" for (unsigned int ii = 0; ii < foo.size(); ++ii)\n"
" {\n"
" foo[ii] = 0;\n"
" }\n"
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
}
{
check("void foo()\n"
"{\n"
" std::vector<int> foo;\n"
" for (unsigned int ii = 0; ii <= foo.size(); ++ii)\n"
" {\n"
" }\n"
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
}
}
};
REGISTER_TEST(TestBufferOverrun)

View File

@ -37,6 +37,8 @@ private:
void run()
{
TEST_CASE(iterator1);
TEST_CASE(STLSize);
TEST_CASE(STLSizeNoErr);
}
void check(const char code[])
@ -52,6 +54,7 @@ private:
// Check char variable usage..
CheckStl checkStl(&tokenizer, this);
checkStl.iterators();
checkStl.stlOutOfBounds();
}
@ -65,6 +68,45 @@ private:
ASSERT_EQUALS("[test.cpp:3]: (error) Same iterator is used with both foo and bar\n", errout.str());
}
void STLSize()
{
check("void foo()\n"
"{\n"
" std::vector<int> foo;\n"
" for (unsigned int ii = 0; ii <= foo.size(); ++ii)\n"
" {\n"
" foo[ii] = 0;\n"
" }\n"
"}\n");
ASSERT_EQUALS(std::string("[test.cpp:6]: (error) When ii == size(), foo [ ii ] is out of bounds\n"), errout.str());
}
void STLSizeNoErr()
{
{
check("void foo()\n"
"{\n"
" std::vector<int> foo;\n"
" for (unsigned int ii = 0; ii < foo.size(); ++ii)\n"
" {\n"
" foo[ii] = 0;\n"
" }\n"
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
}
{
check("void foo()\n"
"{\n"
" std::vector<int> foo;\n"
" for (unsigned int ii = 0; ii <= foo.size(); ++ii)\n"
" {\n"
" }\n"
"}\n");
ASSERT_EQUALS(std::string(""), errout.str());
}
}
};
REGISTER_TEST(TestStl)