buffer overrun: improved checking of global variables

This commit is contained in:
Daniel Marjamäki 2009-02-11 16:12:29 +00:00
parent 4c93b4928b
commit ba3752feb6
3 changed files with 58 additions and 39 deletions

View File

@ -388,7 +388,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
// Checking local variables in a scope
//---------------------------------------------------------------------------
void CheckBufferOverrunClass::CheckBufferOverrun_LocalVariable()
void CheckBufferOverrunClass::CheckBufferOverrun_GlobalAndLocalVariable()
{
int indentlevel = 0;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
@ -399,43 +399,40 @@ void CheckBufferOverrunClass::CheckBufferOverrun_LocalVariable()
else if (tok->str() == "}")
--indentlevel;
else if (indentlevel > 0)
const char *varname[2] = {0};
unsigned int size = 0;
const char *type = 0;
unsigned int varid = 0;
int nextTok = 0;
if (Token::Match(tok, "%type% %var% [ %num% ] ;"))
{
const char *varname[2] = {0};
unsigned int size = 0;
const char *type = 0;
unsigned int varid = 0;
int nextTok = 0;
if (Token::Match(tok, "%type% %var% [ %num% ] ;"))
{
varname[0] = tok->strAt(1);
size = std::strtoul(tok->strAt(3), NULL, 10);
type = tok->aaaa();
varid = tok->tokAt(1)->varId();
nextTok = 6;
}
else if (Token::Match(tok, "[*;{}] %var% = new %type% [ %num% ]"))
{
varname[0] = tok->strAt(1);
size = std::strtoul(tok->strAt(6), NULL, 10);
type = tok->strAt(4);
varid = tok->tokAt(1)->varId();
nextTok = 8;
}
else
{
continue;
}
int total_size = size * _tokenizer->SizeOfType(type);
if (total_size == 0)
continue;
// The callstack is empty
_callStack.clear();
CheckBufferOverrun_CheckScope(tok->tokAt(nextTok), varname, size, total_size, varid);
varname[0] = tok->strAt(1);
size = std::strtoul(tok->strAt(3), NULL, 10);
type = tok->aaaa();
varid = tok->tokAt(1)->varId();
nextTok = 6;
}
else if (indentlevel > 0 && Token::Match(tok, "[*;{}] %var% = new %type% [ %num% ]"))
{
varname[0] = tok->strAt(1);
size = std::strtoul(tok->strAt(6), NULL, 10);
type = tok->strAt(4);
varid = tok->tokAt(1)->varId();
nextTok = 8;
}
else
{
continue;
}
int total_size = size * _tokenizer->SizeOfType(type);
if (total_size == 0)
continue;
// The callstack is empty
_callStack.clear();
CheckBufferOverrun_CheckScope(tok->tokAt(nextTok), varname, size, total_size, varid);
}
}
//---------------------------------------------------------------------------
@ -560,7 +557,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
void CheckBufferOverrunClass::bufferOverrun()
{
CheckBufferOverrun_LocalVariable();
CheckBufferOverrun_GlobalAndLocalVariable();
CheckBufferOverrun_StructVariable();
}
//---------------------------------------------------------------------------

View File

@ -43,8 +43,8 @@ private:
/** Check for buffer overruns - locate struct variables and check them with the .._CheckScope function */
void CheckBufferOverrun_StructVariable();
/** Check for buffer overruns - locate local function variables and check them with the .._CheckScope function */
void CheckBufferOverrun_LocalVariable();
/** Check for buffer overruns - locate global variables and local function variables and check them with the .._CheckScope function */
void CheckBufferOverrun_GlobalAndLocalVariable();
/** 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);

View File

@ -85,6 +85,7 @@ private:
TEST_CASE(buffer_overrun_1);
TEST_CASE(buffer_overrun_2);
TEST_CASE(buffer_overrun_3);
TEST_CASE(sprintf1);
TEST_CASE(snprintf1);
@ -373,6 +374,9 @@ private:
}
void buffer_overrun_1()
{
check("void f()\n"
@ -399,6 +403,24 @@ private:
}
void buffer_overrun_3()
{
check("int a[10];\n"
"\n"
"void foo()\n"
"{\n"
" int i;\n"
" for (i = 0; i <= 10; ++i)\n"
" a[i] = 0;\n"
"}\n");
std::string err(errout.str());
ASSERT_EQUALS(std::string("[test.cpp:7]: (all) Buffer overrun\n"), err);
}
void sprintf1()
{
check("void f()\n"