buffer overrun: improved checking of global variables
This commit is contained in:
parent
4c93b4928b
commit
ba3752feb6
|
@ -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();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue