Refactoring the 'CheckBufferOverrun'
This commit is contained in:
parent
954cccf843
commit
1e379b8ffa
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue