Removed checking of 'dynamic data' it's impossible to determine if it's

false or true positives without deeper analysis.
This commit is contained in:
Daniel Marjamäki 2008-03-24 11:00:04 +00:00
parent c327dc10d8
commit 954cccf843
2 changed files with 35 additions and 121 deletions

View File

@ -1,9 +1,14 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Buffer overrun..
//---------------------------------------------------------------------------
#include "CheckBufferOverrun.h" #include "CheckBufferOverrun.h"
#include "tokenize.h" #include "tokenize.h"
#include "CommonCheck.h" #include "CommonCheck.h"
#include <sstream> #include <sstream>
#include <list>
#include <stdlib.h> // <- strtoul #include <stdlib.h> // <- strtoul
@ -11,114 +16,24 @@
extern bool ShowAll; extern bool ShowAll;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//--------------------------------------------------------------------------- // CallStack used when parsing into subfunctions.
// Writing dynamic data in buffer without bounds checking static std::list<const TOKEN *> CallStack;
//---------------------------------------------------------------------------
static void _DynamicDataCheck(const TOKEN *ftok, const TOKEN *tok) // Modified version of 'ReportError' that also reports the callstack
static void ReportError(const TOKEN *tok, const char errmsg[])
{ {
const char *var2 = tok->str; std::ostringstream ostr;
bool decl = false; std::list<const TOKEN *>::const_iterator it;
unsigned int Var2Count = 0; for ( it = CallStack.begin(); it != CallStack.end(); it++ )
for ( const TOKEN *tok2 = ftok; tok2; tok2 = tok2->next ) ostr << FileLine(*it) << " -> ";
{ ostr << FileLine(tok) << ": " << errmsg;
if (tok2 == tok) ReportErr(ostr.str());
break;
if (match(tok2,"char * var"))
{
decl |= (strcmp(getstr(tok2,2),var2)==0);
tok2 = gettok(tok2,3);
if ( strcmp(tok2->str, "=") == 0 )
{
Var2Count++;
break;
}
}
if (match(tok2,"char var [ ]"))
{
decl |= (strcmp(getstr(tok2,1),var2)==0);
tok2 = gettok(tok2,3);
}
// If ShowAll, only strlen(var2) counts
if ( ShowAll )
{
if (match(tok2,"strlen ( var )") &&
strcmp(getstr(tok2,2),var2)==0)
{
Var2Count++;
break;
}
}
// If not ShowAll, all usage of "var2" counts
else
{
if (strcmp(tok2->str,var2)==0)
{
Var2Count++;
break;
}
}
}
// The size of Var2 isn't checked, is it?
if (decl && Var2Count == 0)
{
std::ostringstream ostr;
ostr << FileLine(tok) << ": A string with unknown length is copied to buffer.";
ReportErr(ostr.str());
}
} }
static void CheckBufferOverrun_DynamicData()
{
for (const TOKEN *ftok = FindFunction(tokens,0); ftok; ftok = FindFunction(ftok->next,0))
{
int indentlevel = 0;
for (const TOKEN *tok = ftok; tok; tok = tok->next)
{
if (tok->str[0] == '{')
indentlevel++;
else if (tok->str[0] == '}')
{
indentlevel--;
if (indentlevel <= 0)
break;
}
if (match(tok,"strcpy ( var , var )") ||
match(tok,"strcat ( var , var )") )
{
_DynamicDataCheck(ftok,gettok(tok,4));
}
if (match(tok,"sprintf ( var"))
{
for ( const TOKEN *tok2 = gettok(tok,3); tok2; tok2 = tok2->next )
{
if (tok2->str[0] == ')')
break;
if (match(tok2,", var ,") || match(tok2,", var )"))
{
_DynamicDataCheck(ftok,tok2->next);
}
}
}
}
}
}
//---------------------------------------------------------------------------
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Buffer overrun.. // Checking local variables in a scope
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const char varname[], const int size, const int total_size ) static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const char varname[], const int size, const int total_size )
@ -147,9 +62,7 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
const char *str = getstr(tok, 2); const char *str = getstr(tok, 2);
if (strtol(str, NULL, 10) >= size) if (strtol(str, NULL, 10) >= size)
{ {
std::ostringstream ostr; ReportError(tok, "Array index out of bounds");
ostr << FileLine(tok) << ": Array index out of bounds";
ReportErr(ostr.str());
} }
continue; continue;
} }
@ -174,9 +87,7 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
(strcmp(var1,varname)==0 || (strcmp(var1,varname)==0 ||
strcmp(var2,varname)==0 ) ) strcmp(var2,varname)==0 ) )
{ {
std::ostringstream ostr; ReportError(tok, "Buffer overrun");
ostr << FileLine(tok) << ": Buffer overrun";
ReportErr(ostr.str());
} }
} }
continue; continue;
@ -233,9 +144,7 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
strcmp(tok2->str,varname)==0 && strcmp(tok2->str,varname)==0 &&
strcmp(getstr(tok2,2),strindex)==0 ) strcmp(getstr(tok2,2),strindex)==0 )
{ {
std::ostringstream ostr; ReportError(tok2, "Buffer overrun");
ostr << FileLine(tok2) << ": Buffer overrun";
ReportErr(ostr.str());
break; break;
} }
@ -265,9 +174,7 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
} }
if (len > 2 && len >= (int)size + 2) if (len > 2 && len >= (int)size + 2)
{ {
std::ostringstream ostr; ReportError(tok, "Buffer overrun");
ostr << FileLine(tok) << ": Buffer overrun";
ReportErr(ostr.str());
} }
continue; continue;
} }
@ -276,6 +183,10 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
// Function call.. // Function call..
if ( match( tok, "var (" ) ) if ( match( tok, "var (" ) )
{ {
// Don't make recursive checking..
if (std::find(CallStack.begin(), CallStack.end(), tok) != CallStack.end())
continue;
unsigned int parlevel = 0, par = 0; unsigned int parlevel = 0, par = 0;
for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next ) for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
{ {
@ -342,7 +253,9 @@ static void CheckBufferOverrun_LocalVariable_CheckScope( const TOKEN *tok, const
ftok = ftok ? ftok->next : 0; ftok = ftok ? ftok->next : 0;
// Check variable usage in the function.. // Check variable usage in the function..
CallStack.push_back( tok );
CheckBufferOverrun_LocalVariable_CheckScope( ftok, parname, size, total_size ); CheckBufferOverrun_LocalVariable_CheckScope( ftok, parname, size, total_size );
CallStack.pop_back();
// break out.. // break out..
break; break;
@ -374,12 +287,19 @@ static void CheckBufferOverrun_LocalVariable()
if (total_size == 0) if (total_size == 0)
continue; continue;
// The callstack is empty
CallStack.clear();
CheckBufferOverrun_LocalVariable_CheckScope( gettok(tok,5), varname, size, total_size ); CheckBufferOverrun_LocalVariable_CheckScope( gettok(tok,5), varname, size, total_size );
} }
} }
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Checking member variables of structs..
//---------------------------------------------------------------------------
static void CheckBufferOverrun_StructVariable_CheckVar( const TOKEN *tok1, const char varname[], const char arrname[], const int arrsize ) static void CheckBufferOverrun_StructVariable_CheckVar( const TOKEN *tok1, const char varname[], const char arrname[], const int arrsize )
{ {
const char *badpattern[] = {"varname",".","arrname","[","","]",NULL}; const char *badpattern[] = {"varname",".","arrname","[","","]",NULL};
@ -456,7 +376,6 @@ static void CheckBufferOverrun_StructVariable()
void CheckBufferOverrun() void CheckBufferOverrun()
{ {
CheckBufferOverrun_DynamicData();
CheckBufferOverrun_LocalVariable(); CheckBufferOverrun_LocalVariable();
CheckBufferOverrun_StructVariable(); CheckBufferOverrun_StructVariable();
} }

View File

@ -372,13 +372,8 @@ static void buffer_overrun()
"{\n" "{\n"
" strcpy(buf, str);\n" " strcpy(buf, str);\n"
"}\n"; "}\n";
const char err7[] =
"[test.cpp:3]: A string with unknown length is copied to buffer.\n"
"[test.cpp:7]: A string with unknown length is copied to buffer.\n"
"[test.cpp:11]: A string with unknown length is copied to buffer.\n"
"[test.cpp:15]: A string with unknown length is copied to buffer.\n";
check( CheckBufferOverrun, __LINE__, test7, err7 ); check( CheckBufferOverrun, __LINE__, test7, "" );
const char test8[] = "struct ABC\n" const char test8[] = "struct ABC\n"
@ -433,7 +428,7 @@ static void buffer_overrun()
" char str[5];\n" " char str[5];\n"
" memclr( str ); // ERROR\n" " memclr( str ); // ERROR\n"
"}\n"; "}\n";
check( CheckBufferOverrun, __LINE__, test11, "[test.cpp:3]: Array index out of bounds\n" ); check( CheckBufferOverrun, __LINE__, test11, "[test.cpp:9] -> [test.cpp:3]: Array index out of bounds\n" );