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()
|
void CheckBufferOverrun()
|
||||||
{
|
{
|
||||||
|
_DynamicData();
|
||||||
|
|
||||||
int indentlevel = 0;
|
int indentlevel = 0;
|
||||||
for (TOKEN *tok = tokens; tok; tok = tok->next)
|
for (TOKEN *tok = tokens; tok; tok = tok->next)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
bool HasErrors;
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
std::string FileLine(TOKEN *tok)
|
std::string FileLine(TOKEN *tok)
|
||||||
{
|
{
|
||||||
|
@ -16,6 +18,7 @@ std::string FileLine(TOKEN *tok)
|
||||||
void ReportErr(const std::string errmsg)
|
void ReportErr(const std::string errmsg)
|
||||||
{
|
{
|
||||||
std::cerr << errmsg << std::endl;
|
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
|
// CppCheck - A function that checks a specified file
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
extern bool HasErrors;
|
||||||
|
|
||||||
static void CppCheck(const char FileName[])
|
static void CppCheck(const char FileName[])
|
||||||
{
|
{
|
||||||
|
HasErrors = false;
|
||||||
|
|
||||||
// Tokenize the file
|
// Tokenize the file
|
||||||
tokens = tokens_back = NULL;
|
tokens = tokens_back = NULL;
|
||||||
Files.clear();
|
Files.clear();
|
||||||
|
@ -74,7 +78,7 @@ static void CppCheck(const char FileName[])
|
||||||
|
|
||||||
|
|
||||||
// Check that the memsets are valid.
|
// 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.
|
// Important: The checking doesn't work on simplified tokens list.
|
||||||
CheckMemset();
|
CheckMemset();
|
||||||
|
|
||||||
|
@ -149,6 +153,10 @@ static void CppCheck(const char FileName[])
|
||||||
|
|
||||||
// Clean up tokens..
|
// Clean up tokens..
|
||||||
DeallocateTokens();
|
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