Moved stloutofbounds check to CheckStl class.
This commit is contained in:
parent
e40c36a6bd
commit
4660b7648d
|
@ -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()
|
void CheckBufferOverrunClass::bufferOverrun()
|
||||||
{
|
{
|
||||||
CheckBufferOverrun_LocalVariable();
|
CheckBufferOverrun_LocalVariable();
|
||||||
CheckBufferOverrun_StructVariable();
|
CheckBufferOverrun_StructVariable();
|
||||||
STLSizeProblems();
|
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -45,12 +45,6 @@ private:
|
||||||
/** Check for buffer overruns - this is the function that performs the actual checking */
|
/** 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);
|
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 Tokenizer *_tokenizer;
|
||||||
const Settings _settings;
|
const Settings _settings;
|
||||||
ErrorLogger *_errorLogger;
|
ErrorLogger *_errorLogger;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,13 @@ public:
|
||||||
CheckStl(const Tokenizer *tokenizer, ErrorLogger *errorLogger);
|
CheckStl(const Tokenizer *tokenizer, ErrorLogger *errorLogger);
|
||||||
~CheckStl();
|
~CheckStl();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds errors like this:
|
||||||
|
* for (unsigned ii = 0; ii <= foo.size(); ++ii)
|
||||||
|
*/
|
||||||
|
void stlOutOfBounds();
|
||||||
|
|
||||||
void iterators();
|
void iterators();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -412,6 +412,9 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
||||||
CheckStl checkStl(&_tokenizer, this);
|
CheckStl checkStl(&_tokenizer, this);
|
||||||
if (ErrorLogger::iteratorUsage())
|
if (ErrorLogger::iteratorUsage())
|
||||||
checkStl.iterators();
|
checkStl.iterators();
|
||||||
|
|
||||||
|
if (ErrorLogger::stlOutOfBounds())
|
||||||
|
checkStl.stlOutOfBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings CppCheck::settings() const
|
Settings CppCheck::settings() const
|
||||||
|
|
|
@ -93,8 +93,6 @@ private:
|
||||||
|
|
||||||
TEST_CASE(varid1);
|
TEST_CASE(varid1);
|
||||||
TEST_CASE(varid2);
|
TEST_CASE(varid2);
|
||||||
TEST_CASE(STLSize);
|
|
||||||
TEST_CASE(STLSizeNoErr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -472,45 +470,6 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS(std::string(""), errout.str());
|
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)
|
REGISTER_TEST(TestBufferOverrun)
|
||||||
|
|
|
@ -37,6 +37,8 @@ private:
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE(iterator1);
|
TEST_CASE(iterator1);
|
||||||
|
TEST_CASE(STLSize);
|
||||||
|
TEST_CASE(STLSizeNoErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(const char code[])
|
void check(const char code[])
|
||||||
|
@ -52,6 +54,7 @@ private:
|
||||||
// Check char variable usage..
|
// Check char variable usage..
|
||||||
CheckStl checkStl(&tokenizer, this);
|
CheckStl checkStl(&tokenizer, this);
|
||||||
checkStl.iterators();
|
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());
|
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)
|
REGISTER_TEST(TestStl)
|
||||||
|
|
Loading…
Reference in New Issue