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();
|
simplifyIfNotNull();
|
||||||
simplifyIfAssign();
|
simplifyIfAssign();
|
||||||
|
|
||||||
|
simplifyNestedStrcat();
|
||||||
|
|
||||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
if (Token::Match(tok, "case %any% : %var%"))
|
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 */
|
/** Replace a "goto" with the statements */
|
||||||
void simplifyGoto();
|
void simplifyGoto();
|
||||||
|
|
||||||
|
/** Expand nested strcat() calls. */
|
||||||
|
void simplifyNestedStrcat();
|
||||||
|
|
||||||
/** Simplify "if else" */
|
/** Simplify "if else" */
|
||||||
void elseif();
|
void elseif();
|
||||||
|
|
||||||
|
|
|
@ -568,6 +568,13 @@ private:
|
||||||
" strcat(n, \"def\");\n"
|
" strcat(n, \"def\");\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (possible error) Buffer overrun\n", errout.str());
|
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()
|
void sprintf1()
|
||||||
|
|
|
@ -108,6 +108,9 @@ private:
|
||||||
|
|
||||||
// Simplify goto..
|
// Simplify goto..
|
||||||
TEST_CASE(goto1);
|
TEST_CASE(goto1);
|
||||||
|
|
||||||
|
// Simplify nested strcat() calls
|
||||||
|
TEST_CASE(strcat1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tok(const char code[])
|
std::string tok(const char code[])
|
||||||
|
@ -1345,6 +1348,21 @@ private:
|
||||||
ASSERT_EQUALS(code, tok(code));
|
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)
|
REGISTER_TEST(TestSimplifyTokens)
|
||||||
|
|
Loading…
Reference in New Issue