Fix ticket #94 (STL container overrun). Check is currently behind --all

This commit is contained in:
Reijo Tomperi 2009-02-09 22:25:44 +00:00
parent 1373e14bc9
commit 9dff3f4c52
3 changed files with 106 additions and 0 deletions

View File

@ -555,12 +555,73 @@ 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->outOfBounds(_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();
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -45,6 +45,12 @@ 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;

View File

@ -93,6 +93,8 @@ private:
TEST_CASE(varid1); TEST_CASE(varid1);
TEST_CASE(varid2); TEST_CASE(varid2);
TEST_CASE(STLSize);
TEST_CASE(STLSizeNoErr);
} }
@ -471,7 +473,44 @@ private:
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)