Buffer overruns, using string with unknown length
This commit is contained in:
parent
7ea6e10f1f
commit
93b3e2e5aa
|
@ -9,6 +9,124 @@
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
TOKEN *findfunction(TOKEN *tok)
|
||||
{
|
||||
int indentlevel = 0, parlevel = 0;
|
||||
for (; tok; tok = tok->next)
|
||||
{
|
||||
if (tok->str[0] == '{')
|
||||
indentlevel++;
|
||||
else if (tok->str[0] == '}')
|
||||
indentlevel--;
|
||||
else if (tok->str[0] == '(')
|
||||
parlevel++;
|
||||
else if (tok->str[0] == ')')
|
||||
parlevel--;
|
||||
|
||||
if (!tok->next)
|
||||
break;
|
||||
|
||||
if (indentlevel==0 && parlevel==0 && IsName(tok->str) && tok->next->str[0]=='(')
|
||||
{
|
||||
for (TOKEN *tok2 = tok->next; tok2; tok2 = tok2->next)
|
||||
{
|
||||
if (tok2->str[0] == ')')
|
||||
{
|
||||
if (tok2->next->str[0] == '{')
|
||||
return tok;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Writing dynamic data in buffer without bounds checking
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void _DynamicDataCheck(TOKEN *ftok, TOKEN *tok)
|
||||
{
|
||||
const char *var2 = tok->str;
|
||||
bool decl = false;
|
||||
unsigned int Var2Count = 0;
|
||||
for ( TOKEN *tok2 = ftok; tok2; tok2 = tok2->next )
|
||||
{
|
||||
if (tok2 == tok)
|
||||
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 (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 _DynamicData()
|
||||
{
|
||||
for (TOKEN *ftok = findfunction(tokens); ftok; ftok = findfunction(ftok->next))
|
||||
{
|
||||
int indentlevel = 0;
|
||||
for (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 ( 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -17,6 +135,8 @@
|
|||
|
||||
void CheckBufferOverrun()
|
||||
{
|
||||
_DynamicData();
|
||||
|
||||
int indentlevel = 0;
|
||||
for (TOKEN *tok = tokens; tok; tok = tok->next)
|
||||
{
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
//---------------------------------------------------------------------------
|
||||
bool HasErrors;
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
std::string FileLine(TOKEN *tok)
|
||||
{
|
||||
|
@ -16,6 +18,7 @@ std::string FileLine(TOKEN *tok)
|
|||
void ReportErr(const std::string errmsg)
|
||||
{
|
||||
std::cerr << errmsg << std::endl;
|
||||
HasErrors = true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
|
10
main.cpp
10
main.cpp
|
@ -65,8 +65,12 @@ int main(int argc, char* argv[])
|
|||
// CppCheck - A function that checks a specified file
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
extern bool HasErrors;
|
||||
|
||||
static void CppCheck(const char FileName[])
|
||||
{
|
||||
HasErrors = false;
|
||||
|
||||
// Tokenize the file
|
||||
tokens = tokens_back = NULL;
|
||||
Files.clear();
|
||||
|
@ -74,7 +78,7 @@ static void CppCheck(const char FileName[])
|
|||
|
||||
|
||||
// Check that the memsets are valid.
|
||||
// This function can do dangerous things if used wrong.
|
||||
// The 'memset' function can do dangerous things if used wrong.
|
||||
// Important: The checking doesn't work on simplified tokens list.
|
||||
CheckMemset();
|
||||
|
||||
|
@ -149,6 +153,10 @@ static void CppCheck(const char FileName[])
|
|||
|
||||
// Clean up tokens..
|
||||
DeallocateTokens();
|
||||
|
||||
// Todo: How should this work? Activated by a command line switch?
|
||||
//if ( ! HasErrors )
|
||||
// std::cout << "No errors found\n";
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[testbufferoverrun7\testbufferoverrun7.cpp:5]: A string with unknown length is copied to buffer.
|
||||
[testbufferoverrun7\testbufferoverrun7.cpp:10]: A string with unknown length is copied to buffer.
|
||||
[testbufferoverrun7\testbufferoverrun7.cpp:15]: A string with unknown length is copied to buffer.
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
|
||||
void f1(char *str)
|
||||
{
|
||||
strcpy(buf,str);
|
||||
}
|
||||
|
||||
void f2(char *str)
|
||||
{
|
||||
strcat(buf,str);
|
||||
}
|
||||
|
||||
void f3(char *str)
|
||||
{
|
||||
sprintf(buf,"%s",str);
|
||||
}
|
Loading…
Reference in New Issue