Fix #1018 (strcat(strcat()) causes assertion in Tokenizer::validate)
Test case provided by povaddict http://sourceforge.net/apps/trac/cppcheck/ticket/1018
This commit is contained in:
parent
c94ecfe1a3
commit
2c51542cf1
|
@ -535,6 +535,23 @@ bool Token::isStandardType() const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Token::move(Token *srcStart, Token *srcEnd, Token *newLocation)
|
||||||
|
{
|
||||||
|
/**[newLocation] -> b -> c -> [srcStart] -> [srcEnd] -> f */
|
||||||
|
|
||||||
|
// Fix the gap, which tokens to be moved will leave
|
||||||
|
srcStart->previous()->next(srcEnd->next());
|
||||||
|
srcEnd->next()->previous(srcStart->previous());
|
||||||
|
|
||||||
|
// Fix the tokens to be moved
|
||||||
|
srcEnd->next(newLocation->next());
|
||||||
|
srcStart->previous(newLocation);
|
||||||
|
|
||||||
|
// Fix the tokens at newLocation
|
||||||
|
newLocation->next()->previous(srcEnd);
|
||||||
|
newLocation->next(srcStart);
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const Token *Token::findmatch(const Token *tok, const char pattern[], unsigned int varId)
|
const Token *Token::findmatch(const Token *tok, const char pattern[], unsigned int varId)
|
||||||
|
|
|
@ -274,6 +274,15 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string strValue() const;
|
std::string strValue() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move srcStart and srcEnd tokens and all tokens between then
|
||||||
|
* into new a location. Only links between tokens are changed.
|
||||||
|
* @param srcStart This is the first token to be moved
|
||||||
|
* @param srcEnd The last token to be moved
|
||||||
|
* @param newLocation srcStart will be placed after this token.
|
||||||
|
*/
|
||||||
|
static void move(Token *srcStart, Token *srcEnd, Token *newLocation);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void next(Token *next)
|
void next(Token *next)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3983,9 +3983,6 @@ void Tokenizer::simplifyNestedStrcat()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert extracted function calls before first strcat call
|
|
||||||
Token *insertPos = tok;
|
|
||||||
|
|
||||||
// find inner strcat call
|
// find inner strcat call
|
||||||
Token *tok2 = tok->tokAt(3);
|
Token *tok2 = tok->tokAt(3);
|
||||||
while (Token::simpleMatch(tok2, "strcat ( strcat"))
|
while (Token::simpleMatch(tok2, "strcat ( strcat"))
|
||||||
|
@ -3993,52 +3990,21 @@ void Tokenizer::simplifyNestedStrcat()
|
||||||
tok2 = tok2->tokAt(2);
|
tok2 = tok2->tokAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Token *end = tok2->next()->link()->next();
|
// If we have this code:
|
||||||
Token *endOfFirstArg = NULL;
|
// strcat(strcat(dst, foo), bar);
|
||||||
std::stack<Token *> brackets;
|
// We move this part of code before all strcat() calls: strcat(dst, foo)
|
||||||
unsigned int lineno = tok->next()->linenr();
|
// And place "dst" token where the code was.
|
||||||
|
Token *prevTok = tok2->previous();
|
||||||
|
|
||||||
// copy tokens to new place
|
// Move tokens to new place
|
||||||
for (Token *cur = tok2; cur != end; cur = cur->next())
|
Token::move(tok2, tok2->next()->link(), tok);
|
||||||
{
|
tok = tok2->next()->link();
|
||||||
insertPos->insertToken(cur->strAt(0));
|
|
||||||
insertPos = insertPos->next();
|
|
||||||
|
|
||||||
if (cur->str() == "," && endOfFirstArg == NULL)
|
// Insert the "dst" token
|
||||||
{
|
prevTok->insertToken(tok2->strAt(2));
|
||||||
endOfFirstArg = cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
// preserve varId
|
// Insert semicolon after the moved strcat()
|
||||||
if (cur->varId())
|
tok->insertToken(";");
|
||||||
{
|
|
||||||
insertPos->varId(cur->varId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// use line number of first strcat token for all new
|
|
||||||
// tokens
|
|
||||||
insertPos->linenr(lineno);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@ private:
|
||||||
|
|
||||||
// Simplify nested strcat() calls
|
// Simplify nested strcat() calls
|
||||||
TEST_CASE(strcat1);
|
TEST_CASE(strcat1);
|
||||||
|
TEST_CASE(strcat2);
|
||||||
|
|
||||||
// Syntax error
|
// Syntax error
|
||||||
TEST_CASE(argumentsWithSameName)
|
TEST_CASE(argumentsWithSameName)
|
||||||
|
@ -1940,6 +1941,15 @@ private:
|
||||||
|
|
||||||
ASSERT_EQUALS(expect, tok(code));
|
ASSERT_EQUALS(expect, tok(code));
|
||||||
}
|
}
|
||||||
|
void strcat2()
|
||||||
|
{
|
||||||
|
const char code[] = "; strcat(strcat(dst, foo[0]), \" \");";
|
||||||
|
const char expect[] = "; "
|
||||||
|
"strcat ( dst , foo [ 0 ] ) ; "
|
||||||
|
"strcat ( dst , \" \" ) ;";
|
||||||
|
|
||||||
|
ASSERT_EQUALS(expect, tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
void argumentsWithSameName()
|
void argumentsWithSameName()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue