Refactoring the 'CheckBufferOverrun'

This commit is contained in:
Daniel Marjamäki 2008-03-24 11:51:16 +00:00
parent 954cccf843
commit 1e379b8ffa
1 changed files with 96 additions and 60 deletions

View File

@ -33,10 +33,10 @@ static void ReportError(const TOKEN *tok, const char errmsg[])
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Checking local variables in a scope // Check array usage..
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const char varname[], const int size, const int total_size ) static void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char varname[], const char arrname[], const int size, const int total_size )
{ {
int indentlevel = 0; int indentlevel = 0;
for ( ; tok; tok = tok->next ) for ( ; tok; tok = tok->next )
@ -57,9 +57,15 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
// Array index.. // Array index..
if (strcmp(tok->str,varname)==0 && match(tok->next,"[ num ]")) if ( match(tok, "var [ num ]") || match(tok, "var . var [ num ]" ) )
{ {
const char *str = getstr(tok, 2); if ( strcmp(tok->str, varname) != 0 )
continue;
if ( arrname && strcmp(getstr(tok, 2), arrname) != 0 )
continue;
const char *str = getstr(tok, (arrname ? 4 : 2));
if (strtol(str, NULL, 10) >= size) if (strtol(str, NULL, 10) >= size)
{ {
ReportError(tok, "Array index out of bounds"); ReportError(tok, "Array index out of bounds");
@ -76,21 +82,45 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
strcmp(tok->str,"strncpy")==0 || strcmp(tok->str,"strncpy")==0 ||
strcmp(tok->str,"fgets")==0 ) strcmp(tok->str,"fgets")==0 )
{ {
if (match(tok->next,"( var , num , num )") || if (arrname == 0)
match(tok->next,"( var , var , num )") )
{ {
const char *var1 = getstr(tok, 2); if (match(tok->next,"( var , num , num )") ||
const char *var2 = getstr(tok, 4); match(tok->next,"( var , var , num )") )
const char *num = getstr(tok, 6); {
const char *var1 = getstr(tok, 2);
const char *var2 = getstr(tok, 4);
const char *num = getstr(tok, 6);
if ( atoi(num)>total_size && if ( atoi(num)>total_size &&
(strcmp(var1,varname)==0 || (strcmp(var1,varname)==0 ||
strcmp(var2,varname)==0 ) ) strcmp(var2,varname)==0 ) )
{
ReportError(tok, "Buffer overrun");
}
}
continue;
}
else
{
int pos = 0;
if ( match(tok->next, "( var . var , var , num )") )
pos = 2;
else if ( match(tok->next, "( var , var . var , num )") )
pos = 4;
else
continue;
if ( strcmp( getstr(tok,pos), varname ) == 0 &&
strcmp( getstr(tok,pos+2), arrname ) == 0 &&
atoi(getstr(tok,8)) > total_size )
{ {
ReportError(tok, "Buffer overrun"); ReportError(tok, "Buffer overrun");
} }
} }
continue;
} }
@ -140,12 +170,27 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
break; break;
} }
if ( match( tok2, "var [ var ]" ) && if ( arrname == 0 )
strcmp(tok2->str,varname)==0 &&
strcmp(getstr(tok2,2),strindex)==0 )
{ {
ReportError(tok2, "Buffer overrun"); if ( match( tok2, "var [ var ]" ) &&
break; strcmp(tok2->str,varname)==0 &&
strcmp(getstr(tok2,2),strindex)==0 )
{
ReportError(tok2, "Buffer overrun");
break;
}
}
else
{
if ( match( tok2, "var . var [ var ]" ) &&
strcmp(tok2->str,varname)==0 &&
strcmp(getstr(tok2,2), arrname) == 0 &&
strcmp(getstr(tok2,4), strindex) == 0 )
{
ReportError(tok2, "Buffer overrun");
break;
}
} }
tok2 = tok2->next; tok2 = tok2->next;
@ -155,33 +200,39 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
// Writing data into array.. // Writing data into array..
if (match(tok,"strcpy ( var , ")) if ( match(tok,"strcpy ( var ") && strcmp(getstr(tok,2),varname)==0 )
{ {
int pos2 = 3;
if ( arrname && match(gettok(tok,3),". var ,") && strcmp(getstr(tok,4),arrname)==0 )
pos2 = 5;
// pos2 should point on the ','
if ( strcmp( getstr(tok, pos2), "," ) )
continue;
int len = 0; int len = 0;
if (strcmp(getstr(tok, 2), varname) == 0) const char *str = getstr(tok, pos2 + 1);
if (str[0] == '\"')
{ {
const char *str = getstr(tok, 4); while (*str)
if (str[0] == '\"')
{ {
while (*str) if (*str=='\\')
{
if (*str=='\\')
str++;
str++; str++;
len++; str++;
} len++;
}
if (len > 2 && len >= (int)size + 2)
{
ReportError(tok, "Buffer overrun");
} }
}
if (len > 2 && len >= (int)size + 2)
{
ReportError(tok, "Buffer overrun");
} }
continue; continue;
} }
// Function call.. // Function call..
if ( match( tok, "var (" ) ) // Todo: Handle struct member variables..
if ( arrname == 0 && match( tok, "var (" ) )
{ {
// Don't make recursive checking.. // Don't make recursive checking..
if (std::find(CallStack.begin(), CallStack.end(), tok) != CallStack.end()) if (std::find(CallStack.begin(), CallStack.end(), tok) != CallStack.end())
@ -254,7 +305,7 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
// Check variable usage in the function.. // Check variable usage in the function..
CallStack.push_back( tok ); CallStack.push_back( tok );
CheckBufferOverrun_LocalVariable_CheckScope( ftok, parname, size, total_size ); CheckBufferOverrun_CheckScope( ftok, parname, 0, size, total_size );
CallStack.pop_back(); CallStack.pop_back();
// break out.. // break out..
@ -268,6 +319,10 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
} }
//---------------------------------------------------------------------------
// Checking local variables in a scope
//---------------------------------------------------------------------------
static void CheckBufferOverrun_LocalVariable() static void CheckBufferOverrun_LocalVariable()
{ {
int indentlevel = 0; int indentlevel = 0;
@ -289,7 +344,7 @@ static void CheckBufferOverrun_LocalVariable()
// The callstack is empty // The callstack is empty
CallStack.clear(); CallStack.clear();
CheckBufferOverrun_LocalVariable_CheckScope( gettok(tok,5), varname, size, total_size ); CheckBufferOverrun_CheckScope( gettok(tok,5), varname, 0, size, total_size );
} }
} }
} }
@ -300,28 +355,6 @@ static void CheckBufferOverrun_LocalVariable()
// Checking member variables of structs.. // Checking member variables of structs..
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static void CheckBufferOverrun_StructVariable_CheckVar( const TOKEN *tok1, const char varname[], const char arrname[], const int arrsize )
{
const char *badpattern[] = {"varname",".","arrname","[","","]",NULL};
badpattern[0] = varname;
badpattern[2] = arrname;
const TOKEN *tok2 = findtoken( tok1, badpattern );
while (tok2)
{
if ( IsNumber( getstr(tok2, 4) ) )
{
if ( atoi( getstr(tok2, 4) ) >= arrsize )
{
std::ostringstream errmsg;
errmsg << FileLine(tok2) << ": Array index out of bounds";
ReportErr(errmsg.str());
}
}
tok2 = findtoken( tok2->next, badpattern );
}
}
//---------------------------------------------------------------------------
static void CheckBufferOverrun_StructVariable() static void CheckBufferOverrun_StructVariable()
{ {
const char *declstruct_pattern[] = {"struct","","{",0}; const char *declstruct_pattern[] = {"struct","","{",0};
@ -346,7 +379,10 @@ static void CheckBufferOverrun_StructVariable()
if ( match(tok2->next, "var var [ num ] ;") ) if ( match(tok2->next, "var var [ num ] ;") )
{ {
const char *arrname = getstr(tok2, 2); const char *arrname = getstr(tok2, 2);
const char *arrsize = getstr(tok2, 4); int arrsize = atoi(getstr(tok2, 4));
int total_size = arrsize * SizeOfType(tok2->next->str);
if (total_size == 0)
continue;
for ( const TOKEN *tok3 = tokens; tok3; tok3 = tok3->next ) for ( const TOKEN *tok3 = tokens; tok3; tok3 = tok3->next )
{ {
@ -357,14 +393,14 @@ static void CheckBufferOverrun_StructVariable()
if ( match( tok3->next, "var ;" ) ) if ( match( tok3->next, "var ;" ) )
{ {
const char *varname = tok3->next->str; const char *varname = tok3->next->str;
CheckBufferOverrun_StructVariable_CheckVar( tok3, varname, arrname, atoi(arrsize) ); CheckBufferOverrun_CheckScope( tok3, varname, arrname, arrsize, total_size );
} }
// Declare pointer: Fred *fred1 // Declare pointer: Fred *fred1
else if ( match(tok3->next, "* var") && tok3->next->next->next && strchr(",);=", tok3->next->next->next->str[0]) ) else if ( match(tok3->next, "* var") && tok3->next->next->next && strchr(",);=", tok3->next->next->next->str[0]) )
{ {
const char *varname = tok3->next->next->str; const char *varname = tok3->next->next->str;
CheckBufferOverrun_StructVariable_CheckVar( tok3, varname, arrname, atoi(arrsize) ); CheckBufferOverrun_CheckScope( tok3, varname, arrname, arrsize, total_size );
} }
} }
} }