Buffer overflow: Fixed two TODO test cases

This commit is contained in:
Daniel Marjamäki 2010-08-05 11:01:47 +02:00
parent 65f7bcbfa5
commit 1b2f16f443
3 changed files with 92 additions and 8 deletions

View File

@ -80,6 +80,25 @@ void CheckBufferOverrun::arrayIndexOutOfBounds(const Token *tok, const ArrayInfo
reportError(tok, Severity::error, "arrayIndexOutOfBounds", oss.str().c_str()); reportError(tok, Severity::error, "arrayIndexOutOfBounds", oss.str().c_str());
} }
void CheckBufferOverrun::arrayIndexOutOfBounds(const std::list<const Token *> &callstack, const ArrayInfo &arrayInfo, const std::vector<int> &index)
{
std::ostringstream oss;
oss << "Array '" << arrayInfo.varname;
for (unsigned int i = 0; i < arrayInfo.num.size(); ++i)
oss << "[" << arrayInfo.num[i] << "]";
oss << "' index ";
if (index.size() == 1)
oss << index[0];
else
{
oss << arrayInfo.varname;
for (unsigned int i = 0; i < index.size(); ++i)
oss << "[" << index[i] << "]";
}
oss << " out of bounds";
reportError(callstack, Severity::error, "arrayIndexOutOfBounds", oss.str().c_str());
}
void CheckBufferOverrun::bufferOverrun(const Token *tok, const std::string &varnames) void CheckBufferOverrun::bufferOverrun(const Token *tok, const std::string &varnames)
{ {
std::string v = varnames; std::string v = varnames;
@ -518,6 +537,72 @@ void CheckBufferOverrun::checkFunctionCall(const Token &tok, unsigned int par, c
} }
} }
} }
// Calling a user function?
// only 1-dimensional arrays can be checked currently
else if (arrayInfo.num.size() == 1)
{
const Token *ftok = _tokenizer->getFunctionTokenByName(tok.str().c_str());
if (Token::Match(ftok, "%var% (") && Token::Match(ftok->next()->link(), ") const| {"))
{
// Get varid for the corresponding parameter..
unsigned int parameter = 1;
unsigned int parameterVarId = 0;
for (const Token *ftok2 = ftok->tokAt(2); ftok2; ftok2 = ftok2->next())
{
if (ftok2->str() == ",")
{
if (parameter >= par)
break;
++parameter;
}
else if (ftok2->str() == ")")
break;
else if (parameter == par && Token::Match(ftok2, "%var% ,|)"))
parameterVarId = ftok2->varId();
}
// No parameterVarId => bail out
if (parameterVarId == 0)
return;
// Step into the function scope..
ftok = ftok->next()->link();
if (!Token::Match(ftok, ") const| {"))
return;
ftok = Token::findmatch(ftok, "{");
ftok = ftok->next();
// Check the parameter usage in the function scope..
for (; ftok; ftok = ftok->next())
{
if (ftok->str() == "if")
break;
if (ftok->str() == "}")
break;
if (ftok->varId() == parameterVarId)
{
if (Token::Match(ftok->previous(), "[=+-*/;{}] %var% [ %num% ]"))
{
long index = MathLib::toLongNumber(ftok->strAt(2));
if (index >= arrayInfo.num[0])
{
std::list<const Token *> callstack;
callstack.push_back(&tok);
callstack.push_back(ftok);
std::vector<int> ints;
ints.push_back(index);
arrayIndexOutOfBounds(callstack, arrayInfo, ints);
}
}
}
}
}
}
} }
@ -842,9 +927,9 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
if (Token::Match(tok, "%var% (")) if (Token::Match(tok, "%var% ("))
{ {
// 1st parameter.. // 1st parameter..
if (Token::Match(tok->tokAt(2), "%varid% ,", arrayInfo.varid)) if (Token::Match(tok->tokAt(2), "%varid% ,|)", arrayInfo.varid))
checkFunctionCall(*tok, 1, arrayInfo); checkFunctionCall(*tok, 1, arrayInfo);
else if (Token::Match(tok->tokAt(2), "%varid% + %num% ,", arrayInfo.varid)) else if (Token::Match(tok->tokAt(2), "%varid% + %num% ,|)", arrayInfo.varid))
{ {
const ArrayInfo ai(arrayInfo.limit(MathLib::toLongNumber(tok->strAt(4)))); const ArrayInfo ai(arrayInfo.limit(MathLib::toLongNumber(tok->strAt(4))));
checkFunctionCall(*tok, 1, ai); checkFunctionCall(*tok, 1, ai);
@ -862,9 +947,9 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
break; break;
if (tok2->str() == ",") if (tok2->str() == ",")
{ {
if (Token::Match(tok2, ", %varid% ,", arrayInfo.varid)) if (Token::Match(tok2, ", %varid% ,|)", arrayInfo.varid))
checkFunctionCall(*tok, 2, arrayInfo); checkFunctionCall(*tok, 2, arrayInfo);
else if (Token::Match(tok2, ", %varid% + %num% ,", arrayInfo.varid)) else if (Token::Match(tok2, ", %varid% + %num% ,|)", arrayInfo.varid))
{ {
const ArrayInfo ai(arrayInfo.limit(MathLib::toLongNumber(tok2->strAt(3)))); const ArrayInfo ai(arrayInfo.limit(MathLib::toLongNumber(tok2->strAt(3))));
checkFunctionCall(*tok, 2, ai); checkFunctionCall(*tok, 2, ai);

View File

@ -177,6 +177,7 @@ public:
void arrayIndexOutOfBounds(const Token *tok, int size, int index); void arrayIndexOutOfBounds(const Token *tok, int size, int index);
void arrayIndexOutOfBounds(const Token *tok, const ArrayInfo &arrayInfo, const std::vector<int> &index); void arrayIndexOutOfBounds(const Token *tok, const ArrayInfo &arrayInfo, const std::vector<int> &index);
void arrayIndexOutOfBounds(const std::list<const Token *> &callstack, const ArrayInfo &arrayInfo, const std::vector<int> &index);
void bufferOverrun(const Token *tok, const std::string &varnames = ""); void bufferOverrun(const Token *tok, const std::string &varnames = "");
void strncatUsage(const Token *tok); void strncatUsage(const Token *tok);
void outOfBounds(const Token *tok, const std::string &what); void outOfBounds(const Token *tok, const std::string &what);

View File

@ -505,8 +505,7 @@ private:
" char str[5];\n" " char str[5];\n"
" memclr( str ); // ERROR\n" " memclr( str ); // ERROR\n"
"}\n"); "}\n");
TODO_ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (error) Array index out of bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (error) Array 'str[5]' index 10 out of bounds\n", errout.str());
ASSERT_EQUALS("", errout.str());
check("static void memclr( int i, char *data )\n" check("static void memclr( int i, char *data )\n"
"{\n" "{\n"
@ -518,8 +517,7 @@ private:
" char str[5];\n" " char str[5];\n"
" memclr( 0, str ); // ERROR\n" " memclr( 0, str ); // ERROR\n"
"}\n"); "}\n");
TODO_ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (error) Array index out of bounds\n", errout.str()); ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (error) Array 'str[5]' index 10 out of bounds\n", errout.str());
ASSERT_EQUALS("", errout.str());
check("static void memclr( int i, char *data )\n" check("static void memclr( int i, char *data )\n"
"{\n" "{\n"