Fixed #629 (Tokenizer: expand nested strcat() calls)
http://sourceforge.net/apps/trac/cppcheck/ticket/629
This commit is contained in:
parent
d86a2505f3
commit
a9273c9d39
|
@ -1629,6 +1629,8 @@ void Tokenizer::simplifyTokenList()
|
|||
simplifyIfNotNull();
|
||||
simplifyIfAssign();
|
||||
|
||||
simplifyNestedStrcat();
|
||||
|
||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||
{
|
||||
if (Token::Match(tok, "case %any% : %var%"))
|
||||
|
@ -3313,8 +3315,69 @@ void Tokenizer::simplifyGoto()
|
|||
}
|
||||
}
|
||||
|
||||
void Tokenizer::simplifyNestedStrcat()
|
||||
{
|
||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||
{
|
||||
if (! Token::Match(tok, "[;{}] strcat ( strcat ("))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// insert extracted function calls before first strcat call
|
||||
Token *insertPos = tok;
|
||||
|
||||
// find inner strcat call
|
||||
Token *tok2 = tok->tokAt(3);
|
||||
while (Token::simpleMatch(tok2, "strcat ( strcat"))
|
||||
{
|
||||
tok2 = tok2->tokAt(2);
|
||||
}
|
||||
|
||||
Token *end = tok2->next()->link()->next();
|
||||
Token *endOfFirstArg = NULL;
|
||||
std::stack<Token *> brackets;
|
||||
|
||||
// copy tokens to new place
|
||||
for (Token *cur = tok2; cur != end; cur = cur->next())
|
||||
{
|
||||
insertPos->insertToken(cur->strAt(0));
|
||||
insertPos = insertPos->next();
|
||||
|
||||
if (cur->str() == "," && endOfFirstArg == NULL)
|
||||
{
|
||||
endOfFirstArg = cur;
|
||||
}
|
||||
|
||||
// preserve varId
|
||||
if (cur->varId())
|
||||
{
|
||||
insertPos->varId(cur->varId());
|
||||
}
|
||||
|
||||
// linkify braces
|
||||
if (insertPos->str() == "(")
|
||||
{
|
||||
brackets.push(insertPos);
|
||||
}
|
||||
else if (insertPos->str() == ")")
|
||||
{
|
||||
Token::createMutualLinks(brackets.top(), insertPos);
|
||||
brackets.pop();
|
||||
}
|
||||
}
|
||||
insertPos->insertToken(";");
|
||||
|
||||
// remove tokens at old place, but don't remove token with
|
||||
// variable name (1st argument)
|
||||
Token::eraseTokens(tok2->previous(), tok2->tokAt(2));
|
||||
Token::eraseTokens(endOfFirstArg->previous(), end);
|
||||
|
||||
// skip just inserted tokens
|
||||
tok = insertPos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -196,6 +196,9 @@ private:
|
|||
/** Replace a "goto" with the statements */
|
||||
void simplifyGoto();
|
||||
|
||||
/** Expand nested strcat() calls. */
|
||||
void simplifyNestedStrcat();
|
||||
|
||||
/** Simplify "if else" */
|
||||
void elseif();
|
||||
|
||||
|
|
|
@ -568,6 +568,13 @@ private:
|
|||
" strcat(n, \"def\");\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:5]: (possible error) Buffer overrun\n", errout.str());
|
||||
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char n[5];\n"
|
||||
" strcat(strcat(n, \"abc\"), \"def\");\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (possible error) Buffer overrun\n", errout.str());
|
||||
}
|
||||
|
||||
void sprintf1()
|
||||
|
|
|
@ -108,6 +108,9 @@ private:
|
|||
|
||||
// Simplify goto..
|
||||
TEST_CASE(goto1);
|
||||
|
||||
// Simplify nested strcat() calls
|
||||
TEST_CASE(strcat1);
|
||||
}
|
||||
|
||||
std::string tok(const char code[])
|
||||
|
@ -1345,6 +1348,21 @@ private:
|
|||
ASSERT_EQUALS(code, tok(code));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void strcat1()
|
||||
{
|
||||
const char code[] = "; strcat(strcat(strcat(strcat(strcat(strcat(dst, \"this \"), \"\"), \"is \"), \"a \"), \"test\"), \".\");";
|
||||
const char expect[] = "; "
|
||||
"strcat ( dst , \"this \" ) ; "
|
||||
"strcat ( dst , \"\" ) ; "
|
||||
"strcat ( dst , \"is \" ) ; "
|
||||
"strcat ( dst , \"a \" ) ; "
|
||||
"strcat ( dst , \"test\" ) ; "
|
||||
"strcat ( dst , \".\" ) ;";
|
||||
|
||||
ASSERT_EQUALS(expect, tok(code));
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestSimplifyTokens)
|
||||
|
|
Loading…
Reference in New Issue