CheckBufferOverrun : Using variable id to check local array variables

This commit is contained in:
Daniel Marjamäki 2008-12-12 20:10:56 +00:00
parent a44c21da08
commit 6383b9d2bd
3 changed files with 43 additions and 15 deletions

View File

@ -64,7 +64,7 @@ void CheckBufferOverrunClass::ReportError(const TOKEN *tok, const char errmsg[])
// Check array usage.. // Check array usage..
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname[], const int size, const int total_size ) void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname[], const int size, const int total_size, unsigned int varid )
{ {
unsigned int varc = 1; unsigned int varc = 1;
while ( varname[varc] ) while ( varname[varc] )
@ -72,8 +72,19 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
varc = 2 * ( varc - 1 ); varc = 2 * ( varc - 1 );
// Array index.. // Array index..
if ( TOKEN::Match(tok, "%var1% [ %num% ]", varname) ) if ( varid > 0 )
{
if ( TOKEN::Match(tok, "%varid% [ %num% ]", 0, 0, varid) )
{
const char *num = tok->strAt(2);
if (strtol(num, NULL, 10) >= size)
{
ReportError(tok->next(), "Array index out of bounds");
}
}
}
else if ( TOKEN::Match(tok, "%var1% [ %num% ]", varname) )
{ {
const char *num = tok->strAt(2 + varc); const char *num = tok->strAt(2 + varc);
if (strtol(num, NULL, 10) >= size) if (strtol(num, NULL, 10) >= size)
@ -97,9 +108,20 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
if ( indentlevel < 0 ) if ( indentlevel < 0 )
return; return;
} }
// Array index.. // Array index..
if ( !tok->isName() && !TOKEN::Match(tok,"[.&]") && TOKEN::Match(tok->next(), "%var1% [ %num% ]", varname) ) if ( varid > 0 )
{
if ( !tok->isName() && !TOKEN::Match(tok,"[.&]") && TOKEN::Match(tok->next(), "%varid% [ %num% ]", 0, 0, varid) )
{
const char *num = tok->strAt(3);
if (strtol(num, NULL, 10) >= size)
{
ReportError(tok->next(), "Array index out of bounds");
}
}
}
else if ( !tok->isName() && !TOKEN::Match(tok,"[.&]") && TOKEN::Match(tok->next(), "%var1% [ %num% ]", varname) )
{ {
const char *num = tok->next()->strAt(2 + varc); const char *num = tok->next()->strAt(2 + varc);
if (strtol(num, NULL, 10) >= size) if (strtol(num, NULL, 10) >= size)
@ -288,7 +310,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
// Check variable usage in the function.. // Check variable usage in the function..
_callStack.push_back( tok ); _callStack.push_back( tok );
CheckBufferOverrun_CheckScope( ftok, parname, size, total_size ); CheckBufferOverrun_CheckScope( ftok, parname, size, total_size, 0 );
_callStack.pop_back(); _callStack.pop_back();
// break out.. // break out..
@ -321,19 +343,22 @@ void CheckBufferOverrunClass::CheckBufferOverrun_LocalVariable()
{ {
const char *varname[2] = {0}; const char *varname[2] = {0};
unsigned int size = 0; unsigned int size = 0;
const char *type = 0; const char *type = 0;
unsigned int varid = 0;
if (TOKEN::Match(tok, "%type% %var% [ %num% ] ;")) if (TOKEN::Match(tok, "%type% %var% [ %num% ] ;"))
{ {
varname[0] = tok->strAt(1); varname[0] = tok->strAt(1);
size = strtoul(tok->strAt(3), NULL, 10); size = strtoul(tok->strAt(3), NULL, 10);
type = tok->aaaa(); type = tok->aaaa();
varid = tok->tokAt(1)->varId();
} }
else if (indentlevel > 0 && TOKEN::Match(tok, "[*;{}] %var% = new %type% [ %num% ]")) else if (indentlevel > 0 && TOKEN::Match(tok, "[*;{}] %var% = new %type% [ %num% ]"))
{ {
varname[0] = tok->strAt(1); varname[0] = tok->strAt(1);
size = strtoul(tok->strAt(6), NULL, 10); size = strtoul(tok->strAt(6), NULL, 10);
type = tok->strAt(4); type = tok->strAt(4);
varid = tok->tokAt(1)->varId();
} }
else else
{ {
@ -346,7 +371,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_LocalVariable()
// The callstack is empty // The callstack is empty
_callStack.clear(); _callStack.clear();
CheckBufferOverrun_CheckScope( tok->tokAt(5), varname, size, total_size ); CheckBufferOverrun_CheckScope( tok->tokAt(5), varname, size, total_size, varid );
} }
} }
} }
@ -413,7 +438,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
if ( TOKEN::Match(tok4, ") {") ) if ( TOKEN::Match(tok4, ") {") )
{ {
const char *names[2] = {varname[1], 0}; const char *names[2] = {varname[1], 0};
CheckBufferOverrun_CheckScope( tok4->tokAt(2), names, arrsize, total_size ); CheckBufferOverrun_CheckScope( tok4->tokAt(2), names, arrsize, total_size, 0 );
break; break;
} }
} }
@ -470,7 +495,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
continue; continue;
// Check variable usage.. // Check variable usage..
CheckBufferOverrun_CheckScope( CheckTok, varname, arrsize, total_size ); CheckBufferOverrun_CheckScope( CheckTok, varname, arrsize, total_size, 0 );
} }
} }
} }

View File

@ -40,7 +40,7 @@ public:
private: private:
void CheckBufferOverrun_StructVariable(); void CheckBufferOverrun_StructVariable();
void CheckBufferOverrun_LocalVariable(); void CheckBufferOverrun_LocalVariable();
void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname[], const int size, const int total_size ); void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname[], const int size, const int total_size, unsigned int varid );
void ReportError(const TOKEN *tok, const char errmsg[]); void ReportError(const TOKEN *tok, const char errmsg[]);
const Tokenizer *_tokenizer; const Tokenizer *_tokenizer;

View File

@ -42,7 +42,10 @@ private:
Tokenizer tokenizer; Tokenizer tokenizer;
std::istringstream istr(code); std::istringstream istr(code);
tokenizer.tokenize( istr, "test.cpp" ); tokenizer.tokenize( istr, "test.cpp" );
tokenizer.simplifyTokenList(); tokenizer.simplifyTokenList();
// Assign variable ids
tokenizer.setVarId();
// Fill function list // Fill function list
tokenizer.fillFunctionList(); tokenizer.fillFunctionList();
@ -80,7 +83,7 @@ private:
TEST_CASE( buffer_overrun_1 ); TEST_CASE( buffer_overrun_1 );
TEST_CASE( buffer_overrun_2 ); TEST_CASE( buffer_overrun_2 );
// TODO TEST_CASE( varid1 ); TEST_CASE( varid1 );
} }