Merge branch 'master' into aleksi/master

This commit is contained in:
Daniel Marjamäki 2009-08-30 16:03:40 +02:00
commit 9ede0e26ab
5 changed files with 85 additions and 20 deletions

View File

@ -348,20 +348,12 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con
// Writing data into array.. // Writing data into array..
if (Token::Match(tok, ("strcpy|strcat ( " + varnames + " , %str% )").c_str())) if (Token::Match(tok, ("strcpy|strcat ( " + varnames + " , %str% )").c_str()))
{ {
int len = 0; size_t len = Token::getStrLength(tok->tokAt(varc + 4));
const char *str = tok->strAt(varc + 4); if (len >= static_cast<size_t>(size))
while (*str)
{
if (*str == '\\')
++str;
++str;
++len;
}
if (len > 2 && len >= (int)size + 2)
{ {
bufferOverrun(tok); bufferOverrun(tok);
continue;
} }
continue;
} }
@ -382,6 +374,23 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con
strncatUsage(tok->tokAt(9)); strncatUsage(tok->tokAt(9));
} }
// Detect few strcat() calls
if (varid > 0 && Token::Match(tok, "strcat ( %varid% , %str% ) ;", varid))
{
size_t charactersAppend = 0;
const Token *tok2 = tok;
while (tok2 && Token::Match(tok2, "strcat ( %varid% , %str% ) ;", varid))
{
charactersAppend += Token::getStrLength(tok2->tokAt(4));
if (charactersAppend >= static_cast<size_t>(size))
{
bufferOverrun(tok2);
break;
}
tok2 = tok2->tokAt(7);
}
}
// sprintf.. // sprintf..
if (varid > 0 && Token::Match(tok, "sprintf ( %varid% , %str% [,)]", varid)) if (varid > 0 && Token::Match(tok, "sprintf ( %varid% , %str% [,)]", varid))
@ -420,15 +429,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const char *varname[], con
{ {
if (tok2->str()[0] == '\"') if (tok2->str()[0] == '\"')
{ {
len -= 2; len += Token::getStrLength(tok2);
const char *str = tok2->str().c_str();
while (*str)
{
if (*str == '\\')
++str;
++str;
++len;
}
} }
} }
if (len >= (int)size) if (len >= (int)size)

View File

@ -491,6 +491,32 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid)
return true; return true;
} }
size_t Token::getStrLength(const Token *tok)
{
assert(tok != NULL);
size_t len = 0;
const char *str = tok->strAt(0);
assert(str[0] == '"');
assert(str[strlen(str)-1] == '"');
while (*str)
{
if (*str == '\\')
++str;
++str;
++len;
}
assert(len >= 2);
// don't count quotes
len -= 2;
return len;
}
bool Token::isStandardType() const bool Token::isStandardType() const
{ {
bool ret = false; bool ret = false;

View File

@ -117,6 +117,15 @@ public:
*/ */
static bool Match(const Token *tok, const char pattern[], unsigned int varid = 0); static bool Match(const Token *tok, const char pattern[], unsigned int varid = 0);
/**
* Return length of C-string.
*
* Should be called for %str% tokens only.
*
* @param tok token with C-string
**/
static size_t getStrLength(const Token *tok);
bool isName() const bool isName() const
{ {
return _isName; return _isName;

View File

@ -93,6 +93,7 @@ private:
TEST_CASE(buffer_overrun_3); TEST_CASE(buffer_overrun_3);
TEST_CASE(buffer_overrun_4); TEST_CASE(buffer_overrun_4);
TEST_CASE(buffer_overrun_5); TEST_CASE(buffer_overrun_5);
TEST_CASE(buffer_overrun_6);
TEST_CASE(sprintf1); TEST_CASE(sprintf1);
TEST_CASE(sprintf2); TEST_CASE(sprintf2);
@ -558,6 +559,16 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void buffer_overrun_6()
{
check("void f()\n"
"{\n"
" char n[5];\n"
" strcat(n, \"abc\");\n"
" strcat(n, \"def\");\n"
"}\n");
ASSERT_EQUALS("[test.cpp:5]: (possible error) Buffer overrun\n", errout.str());
}
void sprintf1() void sprintf1()
{ {

View File

@ -34,6 +34,7 @@ private:
{ {
TEST_CASE(nextprevious); TEST_CASE(nextprevious);
TEST_CASE(multiCompare); TEST_CASE(multiCompare);
TEST_CASE(getStrLength);
} }
void nextprevious() void nextprevious()
@ -78,6 +79,23 @@ private:
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "abcd"))); ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "abcd")));
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "default"))); ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "default")));
} }
void getStrLength()
{
Token *tok = new Token();
tok->str("\"\"");
ASSERT_EQUALS(0, Token::getStrLength(tok));
tok->str("\"test\"");
ASSERT_EQUALS(4, Token::getStrLength(tok));
tok->str("\"test \\\\test\"");
ASSERT_EQUALS(10, Token::getStrLength(tok));
Tokenizer::deleteTokens(tok);
}
}; };
REGISTER_TEST(TestTOKEN) REGISTER_TEST(TestTOKEN)