Fix crash bug #8579 (#1238)

* Added declaration for deletePrevious function

* Added definition for deletePrevious function

* Fixed crash from deleteThis invalidating pointers

The crash was caused by deleteThis() invalidating the pointer to a constant variable usage.  This happened when a usage followed an assignment.  This fixes bug #8579.

* Added tokensFront to match tokensBack

This means deletePrevious can set the list's front if necessary.

* Initialised tokensFront in appropriate places

* Switched to using default Token constructor

* Switched to using Token default constructor

* Switched to using default constructor for Token

* Added missing argument to Token constructor

* Changed to use default constructor for Tokens

* Switched to using default constructor for Tokens

* Switched to using default constructor for Token

* Added new test for deleting front Token

Also made sure to use the correct constructor for Token in other tests.

* Syntax error

* Replaced tokensFront and tokensBack with a struct

This decreases the size of the Token class for performance purposes.

* Replaced tokensFront and tokensBack with a struct

* Added tokensFrontBack to destructor

* Reworked to use TokensBackFront struct

Also ran astyle.

* Reworked to use TokenList's TokensFrontBack member

* Reworked to use TokensFrontBack struct

* Reworked to use TokensFrontBack struct

* Reworked to work with TokensFrontBack struct

* Removed unnecessary scope operator

* Added missing parentheses

* Fixed syntax error

* Removed unnecessary constructor

* Default constructor now 0-initialises everything

This is safer for not using a temporary TokensFrontBack object, and doesn't use delegating constructors which aren't supported yet.

* Fixed unsafe null check

* Added missing explicit keyword

* Fixing stylistic nits

Removed default constructor as it has been superseded by the single-argument constructor with a default argument value.
Renamed listEnds to tokensFrontBack.
Fixed if statement that was supposed to be adding safety but would actually cause a crash if tokensFrontBack was null.

* Fixing stylistic nits

Removed default constructor and replaced it with a single-argument constructor with a default value.

* Fixing stylistic nits

Renamed _listEnds to _tokensFrontBack.

* Fixing stylistic nits

Renamed _listEnds to _tokensFrontBack.
This commit is contained in:
rebnridgway 2018-05-25 06:15:05 +01:00 committed by Daniel Marjamäki
parent 1af983dd95
commit 42a65c5160
10 changed files with 172 additions and 117 deletions

View File

@ -1329,7 +1329,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
top = top->astParent(); top = top->astParent();
const ValueType *valuetype = top->argumentType(); const ValueType *valuetype = top->argumentType();
if (valuetype && valuetype->type >= ValueType::Type::BOOL) { if (valuetype && valuetype->type >= ValueType::Type::BOOL) {
typeToken = tempToken = new Token(nullptr); typeToken = tempToken = new Token();
if (valuetype->pointer && valuetype->constness & 1) { if (valuetype->pointer && valuetype->constness & 1) {
tempToken->str("const"); tempToken->str("const");
tempToken->insertToken("a"); tempToken->insertToken("a");
@ -1406,7 +1406,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
if (function->retType->classScope->enumType) if (function->retType->classScope->enumType)
typeToken = function->retType->classScope->enumType; typeToken = function->retType->classScope->enumType;
else { else {
tempToken = new Token(nullptr); tempToken = new Token();
tempToken->fileIndex(tok1->fileIndex()); tempToken->fileIndex(tok1->fileIndex());
tempToken->linenr(tok1->linenr()); tempToken->linenr(tok1->linenr());
tempToken->str("int"); tempToken->str("int");
@ -1427,7 +1427,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
if (function->retType->classScope->enumType) if (function->retType->classScope->enumType)
typeToken = function->retType->classScope->enumType; typeToken = function->retType->classScope->enumType;
else { else {
tempToken = new Token(nullptr); tempToken = new Token();
tempToken->fileIndex(tok1->fileIndex()); tempToken->fileIndex(tok1->fileIndex());
tempToken->linenr(tok1->linenr()); tempToken->linenr(tok1->linenr());
tempToken->str("int"); tempToken->str("int");
@ -1452,7 +1452,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
// check for some common well known functions // check for some common well known functions
else if (isCPP && ((Token::Match(tok1->previous(), "%var% . size|empty|c_str ( ) [,)]") && isStdContainer(tok1->previous())) || else if (isCPP && ((Token::Match(tok1->previous(), "%var% . size|empty|c_str ( ) [,)]") && isStdContainer(tok1->previous())) ||
(Token::Match(tok1->previous(), "] . size|empty|c_str ( ) [,)]") && isStdContainer(tok1->previous()->link()->previous())))) { (Token::Match(tok1->previous(), "] . size|empty|c_str ( ) [,)]") && isStdContainer(tok1->previous()->link()->previous())))) {
tempToken = new Token(nullptr); tempToken = new Token();
tempToken->fileIndex(tok1->fileIndex()); tempToken->fileIndex(tok1->fileIndex());
tempToken->linenr(tok1->linenr()); tempToken->linenr(tok1->linenr());
if (tok1->next()->str() == "size") { if (tok1->next()->str() == "size") {
@ -1513,7 +1513,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
if (variableInfo->type() && variableInfo->type()->classScope && variableInfo->type()->classScope->enumType) if (variableInfo->type() && variableInfo->type()->classScope && variableInfo->type()->classScope->enumType)
typeToken = variableInfo->type()->classScope->enumType; typeToken = variableInfo->type()->classScope->enumType;
else { else {
tempToken = new Token(nullptr); tempToken = new Token();
tempToken->fileIndex(tok1->fileIndex()); tempToken->fileIndex(tok1->fileIndex());
tempToken->linenr(tok1->linenr()); tempToken->linenr(tok1->linenr());
tempToken->str("int"); tempToken->str("int");
@ -1552,7 +1552,7 @@ bool CheckIO::ArgumentInfo::isStdVectorOrString()
_template = true; _template = true;
return true; return true;
} else if (variableInfo->isStlType(stl_string)) { } else if (variableInfo->isStlType(stl_string)) {
tempToken = new Token(nullptr); tempToken = new Token();
tempToken->fileIndex(variableInfo->typeStartToken()->fileIndex()); tempToken->fileIndex(variableInfo->typeStartToken()->fileIndex());
tempToken->linenr(variableInfo->typeStartToken()->linenr()); tempToken->linenr(variableInfo->typeStartToken()->linenr());
if (variableInfo->typeStartToken()->strAt(2) == "string") if (variableInfo->typeStartToken()->strAt(2) == "string")
@ -1570,7 +1570,7 @@ bool CheckIO::ArgumentInfo::isStdVectorOrString()
_template = true; _template = true;
return true; return true;
} else if (Token::Match(nameTok, "std :: string|wstring")) { } else if (Token::Match(nameTok, "std :: string|wstring")) {
tempToken = new Token(nullptr); tempToken = new Token();
tempToken->fileIndex(variableInfo->typeStartToken()->fileIndex()); tempToken->fileIndex(variableInfo->typeStartToken()->fileIndex());
tempToken->linenr(variableInfo->typeStartToken()->linenr()); tempToken->linenr(variableInfo->typeStartToken()->linenr());
if (nameTok->strAt(2) == "string") if (nameTok->strAt(2) == "string")

View File

@ -688,7 +688,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
std::set<unsigned int> extravar; std::set<unsigned int> extravar;
// The first token should be ";" // The first token should be ";"
Token* rethead = new Token(nullptr); Token* rethead = new Token();
rethead->str(";"); rethead->str(";");
rethead->linenr(tok->linenr()); rethead->linenr(tok->linenr());
rethead->fileIndex(tok->fileIndex()); rethead->fileIndex(tok->fileIndex());

View File

@ -35,8 +35,8 @@
const std::list<ValueFlow::Value> Token::emptyValueList; const std::list<ValueFlow::Value> Token::emptyValueList;
Token::Token(Token **tokens) : Token::Token(TokensFrontBack *tokensFrontBack) :
tokensBack(tokens), tokensFrontBack(tokensFrontBack),
_next(nullptr), _next(nullptr),
_previous(nullptr), _previous(nullptr),
_link(nullptr), _link(nullptr),
@ -219,8 +219,28 @@ void Token::deleteNext(unsigned long index)
if (_next) if (_next)
_next->previous(this); _next->previous(this);
else if (tokensBack) else if (tokensFrontBack)
*tokensBack = this; tokensFrontBack->back = this;
}
void Token::deletePrevious(unsigned long index)
{
while (_previous && index) {
Token *p = _previous;
// #8154 we are about to be unknown -> destroy the link to us
if (p->_link && p->_link->_link == p)
p->_link->link(nullptr);
_previous = p->previous();
delete p;
--index;
}
if (_previous)
_previous->next(this);
else if (tokensFrontBack)
tokensFrontBack->front = this;
} }
void Token::swapWithNext() void Token::swapWithNext()
@ -312,10 +332,10 @@ void Token::replace(Token *replaceThis, Token *start, Token *end)
start->previous(replaceThis->previous()); start->previous(replaceThis->previous());
end->next(replaceThis->next()); end->next(replaceThis->next());
if (end->tokensBack && *(end->tokensBack) == end) { if (end->tokensFrontBack && end->tokensFrontBack->back == end) {
while (end->next()) while (end->next())
end = end->next(); end = end->next();
*(end->tokensBack) = end; end->tokensFrontBack->back = end;
} }
// Update _progressValue, fileIndex and linenr // Update _progressValue, fileIndex and linenr
@ -906,7 +926,7 @@ void Token::insertToken(const std::string &tokenStr, const std::string &original
if (_str.empty()) if (_str.empty())
newToken = this; newToken = this;
else else
newToken = new Token(tokensBack); newToken = new Token(tokensFrontBack);
newToken->str(tokenStr); newToken->str(tokenStr);
if (!originalNameStr.empty()) if (!originalNameStr.empty())
newToken->originalName(originalNameStr); newToken->originalName(originalNameStr);
@ -929,8 +949,8 @@ void Token::insertToken(const std::string &tokenStr, const std::string &original
if (this->next()) { if (this->next()) {
newToken->next(this->next()); newToken->next(this->next());
newToken->next()->previous(newToken); newToken->next()->previous(newToken);
} else if (tokensBack) { } else if (tokensFrontBack) {
*tokensBack = newToken; tokensFrontBack->back = newToken;
} }
this->next(newToken); this->next(newToken);
newToken->previous(this); newToken->previous(this);

View File

@ -39,6 +39,14 @@ class Type;
class ValueType; class ValueType;
class Variable; class Variable;
/**
* @brief This struct stores pointers to the front and back tokens of the list this token is in.
*/
struct TokensFrontBack {
Token *front;
Token *back;
};
/// @addtogroup Core /// @addtogroup Core
/// @{ /// @{
@ -54,10 +62,9 @@ class Variable;
*/ */
class CPPCHECKLIB Token { class CPPCHECKLIB Token {
private: private:
Token **tokensBack; TokensFrontBack* tokensFrontBack;
// Not implemented.. // Not implemented..
Token();
Token(const Token &); Token(const Token &);
Token operator=(const Token &); Token operator=(const Token &);
@ -71,7 +78,7 @@ public:
eNone eNone
}; };
explicit Token(Token **tokens); explicit Token(TokensFrontBack *tokensFrontBack = nullptr);
~Token(); ~Token();
template<typename T> template<typename T>
@ -97,6 +104,11 @@ public:
*/ */
void deleteNext(unsigned long index = 1); void deleteNext(unsigned long index = 1);
/**
* Unlink and delete the previous 'index' tokens.
*/
void deletePrevious(unsigned long index = 1);
/** /**
* Swap the contents of this token with the next token. * Swap the contents of this token with the next token.
*/ */

View File

@ -3372,7 +3372,7 @@ bool Tokenizer::simplifySizeof()
else if (Token::Match(tok->previous(), "%type% %name% [ %num% ] [,)]") || else if (Token::Match(tok->previous(), "%type% %name% [ %num% ] [,)]") ||
Token::Match(tok->tokAt(-2), "%type% * %name% [ %num% ] [,)]")) { Token::Match(tok->tokAt(-2), "%type% * %name% [ %num% ] [,)]")) {
Token tempTok(nullptr); Token tempTok;
tempTok.str("*"); tempTok.str("*");
sizeOfVar[varId] = sizeOfType(&tempTok); sizeOfVar[varId] = sizeOfType(&tempTok);
declTokOfVar[varId] = tok; declTokOfVar[varId] = tok;
@ -6445,7 +6445,16 @@ bool Tokenizer::simplifyKnownVariables()
while (startTok->next()->str() != ";") while (startTok->next()->str() != ";")
startTok->deleteNext(); startTok->deleteNext();
startTok->deleteNext(); startTok->deleteNext();
// #8579 if we can we want another token to delete startTok. if we can't it doesn't matter
if (startTok->previous()) {
startTok->previous()->deleteNext();
} else if (startTok->next()) {
startTok->next()->deletePrevious();
} else {
startTok->deleteThis(); startTok->deleteThis();
}
startTok = nullptr;
constantVar->second = nullptr; constantVar->second = nullptr;
ret = true; ret = true;

View File

@ -38,8 +38,7 @@ static const unsigned int AST_MAX_DEPTH = 50U;
TokenList::TokenList(const Settings* settings) : TokenList::TokenList(const Settings* settings) :
_front(nullptr), _tokensFrontBack(),
_back(nullptr),
_settings(settings), _settings(settings),
_isC(false), _isC(false),
_isCPP(false) _isCPP(false)
@ -66,9 +65,9 @@ const std::string& TokenList::getSourceFilePath() const
// Deallocate lists.. // Deallocate lists..
void TokenList::deallocateTokens() void TokenList::deallocateTokens()
{ {
deleteTokens(_front); deleteTokens(_tokensFrontBack.front);
_front = nullptr; _tokensFrontBack.front = nullptr;
_back = nullptr; _tokensFrontBack.back = nullptr;
_files.clear(); _files.clear();
} }
@ -142,18 +141,18 @@ void TokenList::addtoken(std::string str, const unsigned int lineno, const unsig
str = MathLib::value(str).str() + suffix; str = MathLib::value(str).str() + suffix;
} }
if (_back) { if (_tokensFrontBack.back) {
_back->insertToken(str); _tokensFrontBack.back->insertToken(str);
} else { } else {
_front = new Token(&_back); _tokensFrontBack.front = new Token(&_tokensFrontBack);
_back = _front; _tokensFrontBack.back = _tokensFrontBack.front;
_back->str(str); _tokensFrontBack.back->str(str);
} }
if (isCPP() && str == "delete") if (isCPP() && str == "delete")
_back->isKeyword(true); _tokensFrontBack.back->isKeyword(true);
_back->linenr(lineno); _tokensFrontBack.back->linenr(lineno);
_back->fileIndex(fileno); _tokensFrontBack.back->fileIndex(fileno);
} }
void TokenList::addtoken(const Token * tok, const unsigned int lineno, const unsigned int fileno) void TokenList::addtoken(const Token * tok, const unsigned int lineno, const unsigned int fileno)
@ -161,19 +160,19 @@ void TokenList::addtoken(const Token * tok, const unsigned int lineno, const uns
if (tok == nullptr) if (tok == nullptr)
return; return;
if (_back) { if (_tokensFrontBack.back) {
_back->insertToken(tok->str(), tok->originalName()); _tokensFrontBack.back->insertToken(tok->str(), tok->originalName());
} else { } else {
_front = new Token(&_back); _tokensFrontBack.front = new Token(&_tokensFrontBack);
_back = _front; _tokensFrontBack.back = _tokensFrontBack.front;
_back->str(tok->str()); _tokensFrontBack.back->str(tok->str());
if (!tok->originalName().empty()) if (!tok->originalName().empty())
_back->originalName(tok->originalName()); _tokensFrontBack.back->originalName(tok->originalName());
} }
_back->linenr(lineno); _tokensFrontBack.back->linenr(lineno);
_back->fileIndex(fileno); _tokensFrontBack.back->fileIndex(fileno);
_back->flags(tok->flags()); _tokensFrontBack.back->flags(tok->flags());
} }
@ -305,20 +304,20 @@ void TokenList::createTokens(const simplecpp::TokenList *tokenList)
if (str.size() > 1 && str[0] == '.' && std::isdigit(str[1])) if (str.size() > 1 && str[0] == '.' && std::isdigit(str[1]))
str = '0' + str; str = '0' + str;
if (_back) { if (_tokensFrontBack.back) {
_back->insertToken(str); _tokensFrontBack.back->insertToken(str);
} else { } else {
_front = new Token(&_back); _tokensFrontBack.front = new Token(&_tokensFrontBack);
_back = _front; _tokensFrontBack.back = _tokensFrontBack.front;
_back->str(str); _tokensFrontBack.back->str(str);
} }
if (isCPP() && _back->str() == "delete") if (isCPP() && _tokensFrontBack.back->str() == "delete")
_back->isKeyword(true); _tokensFrontBack.back->isKeyword(true);
_back->fileIndex(tok->location.fileIndex); _tokensFrontBack.back->fileIndex(tok->location.fileIndex);
_back->linenr(tok->location.line); _tokensFrontBack.back->linenr(tok->location.line);
_back->col(tok->location.col); _tokensFrontBack.back->col(tok->location.col);
_back->isExpandedMacro(!tok->macro.empty()); _tokensFrontBack.back->isExpandedMacro(!tok->macro.empty());
} }
if (_settings && _settings->relativePaths) { if (_settings && _settings->relativePaths) {
@ -326,7 +325,7 @@ void TokenList::createTokens(const simplecpp::TokenList *tokenList)
_files[i] = Path::getRelativePath(_files[i], _settings->basePaths); _files[i] = Path::getRelativePath(_files[i], _settings->basePaths);
} }
Token::assignProgressValues(_front); Token::assignProgressValues(_tokensFrontBack.front);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -1164,7 +1163,7 @@ static Token * createAstAtToken(Token *tok, bool cpp)
void TokenList::createAst() void TokenList::createAst()
{ {
for (Token *tok = _front; tok; tok = tok ? tok->next() : nullptr) { for (Token *tok = _tokensFrontBack.front; tok; tok = tok ? tok->next() : nullptr) {
tok = createAstAtToken(tok, isCPP()); tok = createAstAtToken(tok, isCPP());
} }
} }
@ -1173,7 +1172,7 @@ void TokenList::validateAst() const
{ {
// Check for some known issues in AST to avoid crash/hang later on // Check for some known issues in AST to avoid crash/hang later on
std::set < const Token* > safeAstTokens; // list of "safe" AST tokens without endless recursion std::set < const Token* > safeAstTokens; // list of "safe" AST tokens without endless recursion
for (const Token *tok = _front; tok; tok = tok->next()) { for (const Token *tok = _tokensFrontBack.front; tok; tok = tok->next()) {
// Syntax error if binary operator only has 1 operand // Syntax error if binary operator only has 1 operand
if ((tok->isAssignmentOp() || tok->isComparisonOp() || Token::Match(tok,"[|^/%]")) && tok->astOperand1() && !tok->astOperand2()) if ((tok->isAssignmentOp() || tok->isComparisonOp() || Token::Match(tok,"[|^/%]")) && tok->astOperand1() && !tok->astOperand2())
throw InternalError(tok, "Syntax Error: AST broken, binary operator has only one operand.", InternalError::AST); throw InternalError(tok, "Syntax Error: AST broken, binary operator has only one operand.", InternalError::AST);
@ -1217,7 +1216,7 @@ bool TokenList::validateToken(const Token* tok) const
{ {
if (!tok) if (!tok)
return true; return true;
for (const Token *t = _front; t; t = t->next()) { for (const Token *t = _tokensFrontBack.front; t; t = t->next()) {
if (tok==t) if (tok==t)
return true; return true;
} }

View File

@ -22,6 +22,7 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include "config.h" #include "config.h"
#include "token.h"
#include <string> #include <string>
#include <vector> #include <vector>
@ -104,18 +105,18 @@ public:
/** get first token of list */ /** get first token of list */
const Token *front() const { const Token *front() const {
return _front; return _tokensFrontBack.front;
} }
Token *front() { Token *front() {
return _front; return _tokensFrontBack.front;
} }
/** get last token of list */ /** get last token of list */
const Token *back() const { const Token *back() const {
return _back; return _tokensFrontBack.back;
} }
Token *back() { Token *back() {
return _back; return _tokensFrontBack.back;
} }
/** /**
@ -181,7 +182,7 @@ private:
TokenList &operator=(const TokenList &); TokenList &operator=(const TokenList &);
/** Token list */ /** Token list */
Token *_front, *_back; TokensFrontBack _tokensFrontBack;
/** filenames for the tokenized source code (source + included) */ /** filenames for the tokenized source code (source + included) */
std::vector<std::string> _files; std::vector<std::string> _files;

View File

@ -3149,7 +3149,7 @@ private:
ASSERT_EQUALS(10, CheckBufferOverrun::countSprintfLength("\\\\\\\\Hello%d \\0Text\\\\\\\\", unknownParameter)); ASSERT_EQUALS(10, CheckBufferOverrun::countSprintfLength("\\\\\\\\Hello%d \\0Text\\\\\\\\", unknownParameter));
ASSERT_EQUALS(4, CheckBufferOverrun::countSprintfLength("%%%%%d", unknownParameter)); ASSERT_EQUALS(4, CheckBufferOverrun::countSprintfLength("%%%%%d", unknownParameter));
Token strTok(0); Token strTok;
std::list<const Token*> stringAsParameter(1, &strTok); std::list<const Token*> stringAsParameter(1, &strTok);
strTok.str("\"\""); strTok.str("\"\"");
ASSERT_EQUALS(4, CheckBufferOverrun::countSprintfLength("str%s", stringAsParameter)); ASSERT_EQUALS(4, CheckBufferOverrun::countSprintfLength("str%s", stringAsParameter));
@ -3164,7 +3164,7 @@ private:
ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%5.6s", stringAsParameter)); ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%5.6s", stringAsParameter));
ASSERT_EQUALS(7, CheckBufferOverrun::countSprintfLength("%6.6s", stringAsParameter)); ASSERT_EQUALS(7, CheckBufferOverrun::countSprintfLength("%6.6s", stringAsParameter));
Token numTok(0); Token numTok;
numTok.str("12345"); numTok.str("12345");
std::list<const Token*> intAsParameter(1, &numTok); std::list<const Token*> intAsParameter(1, &numTok);
ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%02ld", intAsParameter)); ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%02ld", intAsParameter));
@ -3179,14 +3179,14 @@ private:
ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%1.5x", intAsParameter)); ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%1.5x", intAsParameter));
ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%5.1x", intAsParameter)); ASSERT_EQUALS(6, CheckBufferOverrun::countSprintfLength("%5.1x", intAsParameter));
Token floatTok(0); Token floatTok;
floatTok.str("1.12345f"); floatTok.str("1.12345f");
std::list<const Token*> floatAsParameter(1, &floatTok); std::list<const Token*> floatAsParameter(1, &floatTok);
TODO_ASSERT_EQUALS(5, 3, CheckBufferOverrun::countSprintfLength("%.2f", floatAsParameter)); TODO_ASSERT_EQUALS(5, 3, CheckBufferOverrun::countSprintfLength("%.2f", floatAsParameter));
ASSERT_EQUALS(9, CheckBufferOverrun::countSprintfLength("%8.2f", floatAsParameter)); ASSERT_EQUALS(9, CheckBufferOverrun::countSprintfLength("%8.2f", floatAsParameter));
TODO_ASSERT_EQUALS(5, 3, CheckBufferOverrun::countSprintfLength("%2.2f", floatAsParameter)); TODO_ASSERT_EQUALS(5, 3, CheckBufferOverrun::countSprintfLength("%2.2f", floatAsParameter));
Token floatTok2(0); Token floatTok2;
floatTok2.str("100.12345f"); floatTok2.str("100.12345f");
std::list<const Token*> floatAsParameter2(1, &floatTok2); std::list<const Token*> floatAsParameter2(1, &floatTok2);
TODO_ASSERT_EQUALS(7, 3, CheckBufferOverrun::countSprintfLength("%2.2f", floatAsParameter2)); TODO_ASSERT_EQUALS(7, 3, CheckBufferOverrun::countSprintfLength("%2.2f", floatAsParameter2));

View File

@ -858,7 +858,7 @@ private:
unsigned int sizeofFromTokenizer(const char type[]) { unsigned int sizeofFromTokenizer(const char type[]) {
Tokenizer tokenizer(&settings0, this); Tokenizer tokenizer(&settings0, this);
tokenizer.fillTypeSizes(); tokenizer.fillTypeSizes();
Token tok1(0); Token tok1;
tok1.str(type); tok1.str(type);
return tokenizer.sizeOfType(&tok1); return tokenizer.sizeOfType(&tok1);
} }

View File

@ -61,6 +61,7 @@ private:
TEST_CASE(strValue); TEST_CASE(strValue);
TEST_CASE(deleteLast); TEST_CASE(deleteLast);
TEST_CASE(deleteFirst);
TEST_CASE(nextArgument); TEST_CASE(nextArgument);
TEST_CASE(eraseTokens); TEST_CASE(eraseTokens);
@ -107,7 +108,7 @@ private:
} }
void nextprevious() const { void nextprevious() const {
Token *token = new Token(0); Token *token = new Token();
token->str("1"); token->str("1");
token->insertToken("2"); token->insertToken("2");
token->next()->insertToken("3"); token->next()->insertToken("3");
@ -139,49 +140,49 @@ private:
void multiCompare() const { void multiCompare() const {
// Test for found // Test for found
Token one(0); Token one;
one.str("one"); one.str("one");
ASSERT_EQUALS(1, Token::multiCompare(&one, "one|two", 0)); ASSERT_EQUALS(1, Token::multiCompare(&one, "one|two", 0));
Token two(0); Token two;
two.str("two"); two.str("two");
ASSERT_EQUALS(1, Token::multiCompare(&two, "one|two", 0)); ASSERT_EQUALS(1, Token::multiCompare(&two, "one|two", 0));
ASSERT_EQUALS(1, Token::multiCompare(&two, "verybig|two|", 0)); ASSERT_EQUALS(1, Token::multiCompare(&two, "verybig|two|", 0));
// Test for empty string found // Test for empty string found
Token notfound(0); Token notfound;
notfound.str("notfound"); notfound.str("notfound");
ASSERT_EQUALS(0, Token::multiCompare(&notfound, "one|two|", 0)); ASSERT_EQUALS(0, Token::multiCompare(&notfound, "one|two|", 0));
// Test for not found // Test for not found
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&notfound, "one|two", 0))); ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&notfound, "one|two", 0)));
Token s(0); Token s;
s.str("s"); s.str("s");
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&s, "verybig|two", 0))); ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&s, "verybig|two", 0)));
Token ne(0); Token ne;
ne.str("ne"); ne.str("ne");
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&ne, "one|two", 0))); ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&ne, "one|two", 0)));
Token a(0); Token a;
a.str("a"); a.str("a");
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&a, "abc|def", 0))); ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&a, "abc|def", 0)));
Token abcd(0); Token abcd;
abcd.str("abcd"); abcd.str("abcd");
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&abcd, "abc|def", 0))); ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&abcd, "abc|def", 0)));
Token def(0); Token def;
def.str("default"); def.str("default");
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&def, "abc|def", 0))); ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(&def, "abc|def", 0)));
// %op% // %op%
Token plus(0); Token plus;
plus.str("+"); plus.str("+");
ASSERT_EQUALS(1, Token::multiCompare(&plus, "one|%op%", 0)); ASSERT_EQUALS(1, Token::multiCompare(&plus, "one|%op%", 0));
ASSERT_EQUALS(1, Token::multiCompare(&plus, "%op%|two", 0)); ASSERT_EQUALS(1, Token::multiCompare(&plus, "%op%|two", 0));
Token x(0); Token x;
x.str("x"); x.str("x");
ASSERT_EQUALS(-1, Token::multiCompare(&x, "one|%op%", 0)); ASSERT_EQUALS(-1, Token::multiCompare(&x, "one|%op%", 0));
ASSERT_EQUALS(-1, Token::multiCompare(&x, "%op%|two", 0)); ASSERT_EQUALS(-1, Token::multiCompare(&x, "%op%|two", 0));
@ -257,13 +258,13 @@ private:
} }
void multiCompare5() const { void multiCompare5() const {
Token tok(0); Token tok;
tok.str("||"); tok.str("||");
ASSERT_EQUALS(true, Token::multiCompare(&tok, "+|%or%|%oror%", 0) >= 0); ASSERT_EQUALS(true, Token::multiCompare(&tok, "+|%or%|%oror%", 0) >= 0);
} }
void getStrLength() const { void getStrLength() const {
Token tok(0); Token tok;
tok.str("\"\""); tok.str("\"\"");
ASSERT_EQUALS(0, (int)Token::getStrLength(&tok)); ASSERT_EQUALS(0, (int)Token::getStrLength(&tok));
@ -279,7 +280,7 @@ private:
} }
void getStrSize() const { void getStrSize() const {
Token tok(0); Token tok;
tok.str("\"abc\""); tok.str("\"abc\"");
ASSERT_EQUALS(sizeof("abc"), Token::getStrSize(&tok)); ASSERT_EQUALS(sizeof("abc"), Token::getStrSize(&tok));
@ -292,7 +293,7 @@ private:
} }
void strValue() const { void strValue() const {
Token tok(0); Token tok;
tok.str("\"\""); tok.str("\"\"");
ASSERT_EQUALS("", tok.strValue()); ASSERT_EQUALS("", tok.strValue());
@ -319,12 +320,25 @@ private:
void deleteLast() const { void deleteLast() const {
Token *tokensBack = 0; TokensFrontBack listEnds{ 0 };
Token tok(&tokensBack); Token **tokensBack = &(listEnds.back);
Token tok(&listEnds);
tok.insertToken("aba"); tok.insertToken("aba");
ASSERT_EQUALS(true, tokensBack == tok.next()); ASSERT_EQUALS(true, *tokensBack == tok.next());
tok.deleteNext(); tok.deleteNext();
ASSERT_EQUALS(true, tokensBack == &tok); ASSERT_EQUALS(true, *tokensBack == &tok);
}
void deleteFirst() const {
TokensFrontBack listEnds{ 0 };
Token **tokensFront = &(listEnds.front);
Token tok(&listEnds);
tok.insertToken("aba");
ASSERT_EQUALS(true, *tokensFront == tok.previous());
tok.deletePrevious();
ASSERT_EQUALS(true, *tokensFront == &tok);
} }
void nextArgument() const { void nextArgument() const {
@ -362,7 +376,7 @@ private:
ASSERT_EQUALS(true, Token::Match(singleChar.tokens(), "[a|bc]")); ASSERT_EQUALS(true, Token::Match(singleChar.tokens(), "[a|bc]"));
ASSERT_EQUALS(false, Token::Match(singleChar.tokens(), "[d|ef]")); ASSERT_EQUALS(false, Token::Match(singleChar.tokens(), "[d|ef]"));
Token multiChar(0); Token multiChar;
multiChar.str("[ab"); multiChar.str("[ab");
ASSERT_EQUALS(false, Token::Match(&multiChar, "[ab|def]")); ASSERT_EQUALS(false, Token::Match(&multiChar, "[ab|def]"));
} }
@ -601,7 +615,7 @@ private:
void isArithmeticalOp() const { void isArithmeticalOp() const {
std::vector<std::string>::const_iterator test_op, test_ops_end = arithmeticalOps.end(); std::vector<std::string>::const_iterator test_op, test_ops_end = arithmeticalOps.end();
for (test_op = arithmeticalOps.begin(); test_op != test_ops_end; ++test_op) { for (test_op = arithmeticalOps.begin(); test_op != test_ops_end; ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS(true, tok.isArithmeticalOp()); ASSERT_EQUALS(true, tok.isArithmeticalOp());
} }
@ -616,7 +630,7 @@ private:
std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end(); std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end();
for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) { for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) {
Token tok(nullptr); Token tok;
tok.str(*other_op); tok.str(*other_op);
ASSERT_EQUALS_MSG(false, tok.isArithmeticalOp(), "Failing arithmetical operator: " + *other_op); ASSERT_EQUALS_MSG(false, tok.isArithmeticalOp(), "Failing arithmetical operator: " + *other_op);
} }
@ -632,7 +646,7 @@ private:
std::vector<std::string>::const_iterator test_op, test_ops_end = test_ops.end(); std::vector<std::string>::const_iterator test_op, test_ops_end = test_ops.end();
for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) { for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS(true, tok.isOp()); ASSERT_EQUALS(true, tok.isOp());
} }
@ -643,7 +657,7 @@ private:
std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end(); std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end();
for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) { for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) {
Token tok(nullptr); Token tok;
tok.str(*other_op); tok.str(*other_op);
ASSERT_EQUALS_MSG(false, tok.isOp(), "Failing normal operator: " + *other_op); ASSERT_EQUALS_MSG(false, tok.isOp(), "Failing normal operator: " + *other_op);
} }
@ -658,7 +672,7 @@ private:
std::vector<std::string>::const_iterator test_op, test_ops_end = test_ops.end(); std::vector<std::string>::const_iterator test_op, test_ops_end = test_ops.end();
for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) { for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS(true, tok.isConstOp()); ASSERT_EQUALS(true, tok.isConstOp());
} }
@ -670,7 +684,7 @@ private:
std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end(); std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end();
for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) { for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) {
Token tok(nullptr); Token tok;
tok.str(*other_op); tok.str(*other_op);
ASSERT_EQUALS_MSG(false, tok.isConstOp(), "Failing normal operator: " + *other_op); ASSERT_EQUALS_MSG(false, tok.isConstOp(), "Failing normal operator: " + *other_op);
} }
@ -686,7 +700,7 @@ private:
std::vector<std::string>::const_iterator test_op, test_ops_end = test_ops.end(); std::vector<std::string>::const_iterator test_op, test_ops_end = test_ops.end();
for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) { for (test_op = test_ops.begin(); test_op != test_ops_end; ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS(true, tok.isExtendedOp()); ASSERT_EQUALS(true, tok.isExtendedOp());
} }
@ -694,7 +708,7 @@ private:
// Negative test against assignment operators // Negative test against assignment operators
std::vector<std::string>::const_iterator other_op, other_ops_end = assignmentOps.end(); std::vector<std::string>::const_iterator other_op, other_ops_end = assignmentOps.end();
for (other_op = assignmentOps.begin(); other_op != other_ops_end; ++other_op) { for (other_op = assignmentOps.begin(); other_op != other_ops_end; ++other_op) {
Token tok(nullptr); Token tok;
tok.str(*other_op); tok.str(*other_op);
ASSERT_EQUALS_MSG(false, tok.isExtendedOp(), "Failing assignment operator: " + *other_op); ASSERT_EQUALS_MSG(false, tok.isExtendedOp(), "Failing assignment operator: " + *other_op);
} }
@ -703,7 +717,7 @@ private:
void isAssignmentOp() const { void isAssignmentOp() const {
std::vector<std::string>::const_iterator test_op, test_ops_end = assignmentOps.end(); std::vector<std::string>::const_iterator test_op, test_ops_end = assignmentOps.end();
for (test_op = assignmentOps.begin(); test_op != test_ops_end; ++test_op) { for (test_op = assignmentOps.begin(); test_op != test_ops_end; ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS(true, tok.isAssignmentOp()); ASSERT_EQUALS(true, tok.isAssignmentOp());
} }
@ -718,7 +732,7 @@ private:
std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end(); std::vector<std::string>::const_iterator other_op, other_ops_end = other_ops.end();
for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) { for (other_op = other_ops.begin(); other_op != other_ops_end; ++other_op) {
Token tok(nullptr); Token tok;
tok.str(*other_op); tok.str(*other_op);
ASSERT_EQUALS_MSG(false, tok.isAssignmentOp(), "Failing assignment operator: " + *other_op); ASSERT_EQUALS_MSG(false, tok.isAssignmentOp(), "Failing assignment operator: " + *other_op);
} }
@ -727,26 +741,26 @@ private:
void operators() const { void operators() const {
std::vector<std::string>::const_iterator test_op; std::vector<std::string>::const_iterator test_op;
for (test_op = extendedOps.begin(); test_op != extendedOps.end(); ++test_op) { for (test_op = extendedOps.begin(); test_op != extendedOps.end(); ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS(Token::eExtendedOp, tok.tokType()); ASSERT_EQUALS(Token::eExtendedOp, tok.tokType());
} }
for (test_op = logicalOps.begin(); test_op != logicalOps.end(); ++test_op) { for (test_op = logicalOps.begin(); test_op != logicalOps.end(); ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS(Token::eLogicalOp, tok.tokType()); ASSERT_EQUALS(Token::eLogicalOp, tok.tokType());
} }
for (test_op = bitOps.begin(); test_op != bitOps.end(); ++test_op) { for (test_op = bitOps.begin(); test_op != bitOps.end(); ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS(Token::eBitOp, tok.tokType()); ASSERT_EQUALS(Token::eBitOp, tok.tokType());
} }
for (test_op = comparisonOps.begin(); test_op != comparisonOps.end(); ++test_op) { for (test_op = comparisonOps.begin(); test_op != comparisonOps.end(); ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS(Token::eComparisonOp, tok.tokType()); ASSERT_EQUALS(Token::eComparisonOp, tok.tokType());
} }
Token tok(nullptr); Token tok;
tok.str("++"); tok.str("++");
ASSERT_EQUALS(Token::eIncDecOp, tok.tokType()); ASSERT_EQUALS(Token::eIncDecOp, tok.tokType());
tok.str("--"); tok.str("--");
@ -754,7 +768,7 @@ private:
} }
void literals() const { void literals() const {
Token tok(nullptr); Token tok;
tok.str("\"foo\""); tok.str("\"foo\"");
ASSERT(tok.tokType() == Token::eString); ASSERT(tok.tokType() == Token::eString);
@ -785,13 +799,13 @@ private:
std::vector<std::string>::const_iterator test_op, test_ops_end = standard_types.end(); std::vector<std::string>::const_iterator test_op, test_ops_end = standard_types.end();
for (test_op = standard_types.begin(); test_op != test_ops_end; ++test_op) { for (test_op = standard_types.begin(); test_op != test_ops_end; ++test_op) {
Token tok(nullptr); Token tok;
tok.str(*test_op); tok.str(*test_op);
ASSERT_EQUALS_MSG(true, tok.isStandardType(), "Failing standard type: " + *test_op); ASSERT_EQUALS_MSG(true, tok.isStandardType(), "Failing standard type: " + *test_op);
} }
// Negative test // Negative test
Token tok(nullptr); Token tok;
tok.str("string"); tok.str("string");
ASSERT_EQUALS(false, tok.isStandardType()); ASSERT_EQUALS(false, tok.isStandardType());
@ -807,7 +821,7 @@ private:
} }
void updateProperties() const { void updateProperties() const {
Token tok(nullptr); Token tok;
tok.str("foobar"); tok.str("foobar");
ASSERT_EQUALS(true, tok.isName()); ASSERT_EQUALS(true, tok.isName());
@ -820,7 +834,7 @@ private:
} }
void updatePropertiesConcatStr() const { void updatePropertiesConcatStr() const {
Token tok(nullptr); Token tok;
tok.str("true"); tok.str("true");
ASSERT_EQUALS(true, tok.isBoolean()); ASSERT_EQUALS(true, tok.isBoolean());
@ -832,39 +846,39 @@ private:
} }
void isNameGuarantees1() const { void isNameGuarantees1() const {
Token tok(nullptr); Token tok;
tok.str("Name"); tok.str("Name");
ASSERT_EQUALS(true, tok.isName()); ASSERT_EQUALS(true, tok.isName());
} }
void isNameGuarantees2() const { void isNameGuarantees2() const {
Token tok(nullptr); Token tok;
tok.str("_name"); tok.str("_name");
ASSERT_EQUALS(true, tok.isName()); ASSERT_EQUALS(true, tok.isName());
} }
void isNameGuarantees3() const { void isNameGuarantees3() const {
Token tok(nullptr); Token tok;
tok.str("_123"); tok.str("_123");
ASSERT_EQUALS(true, tok.isName()); ASSERT_EQUALS(true, tok.isName());
} }
void isNameGuarantees4() const { void isNameGuarantees4() const {
Token tok(nullptr); Token tok;
tok.str("123456"); tok.str("123456");
ASSERT_EQUALS(false, tok.isName()); ASSERT_EQUALS(false, tok.isName());
ASSERT_EQUALS(true, tok.isNumber()); ASSERT_EQUALS(true, tok.isNumber());
} }
void isNameGuarantees5() const { void isNameGuarantees5() const {
Token tok(nullptr); Token tok;
tok.str("a123456"); tok.str("a123456");
ASSERT_EQUALS(true, tok.isName()); ASSERT_EQUALS(true, tok.isName());
ASSERT_EQUALS(false, tok.isNumber()); ASSERT_EQUALS(false, tok.isNumber());
} }
void isNameGuarantees6() const { void isNameGuarantees6() const {
Token tok(nullptr); Token tok;
tok.str("$f"); tok.str("$f");
ASSERT_EQUALS(true, tok.isName()); ASSERT_EQUALS(true, tok.isName());
} }