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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -274,6 +274,15 @@ public:
|
|||
*/
|
||||
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:
|
||||
void next(Token *next)
|
||||
{
|
||||
|
|
|
@ -3983,9 +3983,6 @@ void Tokenizer::simplifyNestedStrcat()
|
|||
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"))
|
||||
|
@ -3993,52 +3990,21 @@ void Tokenizer::simplifyNestedStrcat()
|
|||
tok2 = tok2->tokAt(2);
|
||||
}
|
||||
|
||||
Token *end = tok2->next()->link()->next();
|
||||
Token *endOfFirstArg = NULL;
|
||||
std::stack<Token *> brackets;
|
||||
unsigned int lineno = tok->next()->linenr();
|
||||
// If we have this code:
|
||||
// strcat(strcat(dst, foo), bar);
|
||||
// We move this part of code before all strcat() calls: strcat(dst, foo)
|
||||
// And place "dst" token where the code was.
|
||||
Token *prevTok = tok2->previous();
|
||||
|
||||
// copy tokens to new place
|
||||
for (Token *cur = tok2; cur != end; cur = cur->next())
|
||||
{
|
||||
insertPos->insertToken(cur->strAt(0));
|
||||
insertPos = insertPos->next();
|
||||
// Move tokens to new place
|
||||
Token::move(tok2, tok2->next()->link(), tok);
|
||||
tok = tok2->next()->link();
|
||||
|
||||
if (cur->str() == "," && endOfFirstArg == NULL)
|
||||
{
|
||||
endOfFirstArg = cur;
|
||||
}
|
||||
// Insert the "dst" token
|
||||
prevTok->insertToken(tok2->strAt(2));
|
||||
|
||||
// preserve varId
|
||||
if (cur->varId())
|
||||
{
|
||||
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;
|
||||
// Insert semicolon after the moved strcat()
|
||||
tok->insertToken(";");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ private:
|
|||
|
||||
// Simplify nested strcat() calls
|
||||
TEST_CASE(strcat1);
|
||||
TEST_CASE(strcat2);
|
||||
|
||||
// Syntax error
|
||||
TEST_CASE(argumentsWithSameName)
|
||||
|
@ -1940,6 +1941,15 @@ private:
|
|||
|
||||
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()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue