Fix 10435: False positive: containerOutOfBounds (#3426)

This commit is contained in:
Paul Fultz II 2021-08-29 08:40:10 -05:00 committed by GitHub
parent 2ee880752f
commit 92eb59981d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 48 deletions

View File

@ -2533,3 +2533,51 @@ bool TokenImpl::getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, M
*value = attr->value;
return attr != nullptr;
}
Token* findTypeEnd(Token* tok)
{
while (Token::Match(tok, "%name%|.|::|*|&|&&|<|(|template|decltype|sizeof")) {
if (Token::Match(tok, "(|<"))
tok = tok->link();
if (!tok)
return nullptr;
tok = tok->next();
}
return tok;
}
const Token* findTypeEnd(const Token* tok) {
return findTypeEnd(const_cast<Token*>(tok));
}
Token* findLambdaEndScope(Token* tok)
{
if (!Token::simpleMatch(tok, "["))
return nullptr;
tok = tok->link();
if (!Token::Match(tok, "] (|{"))
return nullptr;
tok = tok->linkAt(1);
if (Token::simpleMatch(tok, "}"))
return tok;
if (Token::simpleMatch(tok, ") {"))
return tok->linkAt(1);
if (!Token::simpleMatch(tok, ")"))
return nullptr;
tok = tok->next();
while (Token::Match(tok, "mutable|constexpr|constval|noexcept|.")) {
if (Token::simpleMatch(tok, "noexcept ("))
tok = tok->linkAt(1);
if (Token::simpleMatch(tok, ".")) {
tok = findTypeEnd(tok);
break;
}
tok = tok->next();
}
if (Token::simpleMatch(tok, "{"))
return tok->link();
return nullptr;
}
const Token* findLambdaEndScope(const Token* tok) {
return findLambdaEndScope(const_cast<Token*>(tok));
}

View File

@ -1395,6 +1395,11 @@ public:
}
};
Token* findTypeEnd(Token* tok);
const Token* findTypeEnd(const Token* tok);
Token* findLambdaEndScope(Token* tok);
const Token* findLambdaEndScope(const Token* tok);
/// @}
//---------------------------------------------------------------------------
#endif // tokenH

View File

@ -7239,8 +7239,34 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
// Split up variable declarations..
// "int a=4;" => "int a; a=4;"
bool finishedwithkr = true;
bool scopeDecl = false;
for (Token *tok = tokBegin; tok != tokEnd; tok = tok->next()) {
if (Token::simpleMatch(tok, "= {")) {
if (Token::Match(tok, "{|;"))
scopeDecl = false;
if (isCPP()) {
if (Token::Match(tok, "class|struct|namespace|union"))
scopeDecl = true;
if (Token::Match(tok, "decltype|noexcept (")) {
tok = tok->next()->link();
// skip decltype(...){...}
if (tok && Token::simpleMatch(tok->previous(), ") {"))
tok = tok->link();
} else if (Token::simpleMatch(tok, "= {") ||
(!scopeDecl && Token::Match(tok, "%name%|> {") &&
!Token::Match(tok, "else|try|do|const|constexpr|override|volatile|noexcept"))) {
if (!tok->next()->link())
syntaxError(tokBegin);
// Check for lambdas before skipping
for (Token* tok2 = tok->next(); tok2 != tok->next()->link(); tok2 = tok2->next()) {
Token* lambdaEnd = findLambdaEndScope(tok2);
if (!lambdaEnd)
continue;
simplifyVarDecl(lambdaEnd->link()->next(), lambdaEnd, only_k_r_fpar);
}
tok = tok->next()->link();
}
} else if (Token::simpleMatch(tok, "= {")) {
tok = tok->next()->link();
}
if (!tok) {

View File

@ -560,52 +560,6 @@ static bool iscast(const Token *tok, bool cpp)
return false;
}
static Token* findTypeEnd(Token* tok)
{
while (Token::Match(tok, "%name%|.|::|*|&|&&|<|(|template|decltype|sizeof")) {
if (Token::Match(tok, "(|<"))
tok = tok->link();
if (!tok)
return nullptr;
tok = tok->next();
}
return tok;
}
static const Token* findTypeEnd(const Token* tok)
{
return findTypeEnd(const_cast<Token*>(tok));
}
static const Token * findLambdaEndScope(const Token *tok)
{
if (!Token::simpleMatch(tok, "["))
return nullptr;
tok = tok->link();
if (!Token::Match(tok, "] (|{"))
return nullptr;
tok = tok->linkAt(1);
if (Token::simpleMatch(tok, "}"))
return tok;
if (Token::simpleMatch(tok, ") {"))
return tok->linkAt(1);
if (!Token::simpleMatch(tok, ")"))
return nullptr;
tok = tok->next();
while (Token::Match(tok, "mutable|constexpr|constval|noexcept|.")) {
if (Token::simpleMatch(tok, "noexcept ("))
tok = tok->linkAt(1);
if (Token::simpleMatch(tok, ".")) {
tok = findTypeEnd(tok);
break;
}
tok = tok->next();
}
if (Token::simpleMatch(tok, "{"))
return tok->link();
return nullptr;
}
// int(1), int*(2), ..
static Token * findCppTypeInitPar(Token *tok)
{

View File

@ -367,7 +367,7 @@ private:
TEST_CASE(simplify_constants4);
TEST_CASE(simplify_constants5);
TEST_CASE(simplify_constants6); // Ticket #5625: Ternary operator as template parameter
TEST_CASE(simplifyVarDeclInitLists);
}
std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Native) {
@ -7063,6 +7063,13 @@ private:
ASSERT_EQUALS(exp, tok(code));
}
}
void simplifyVarDeclInitLists()
{
const char code[] = "std::vector<int> v{a * b, 1};";
const char exp[] = "std :: vector < int > v { a * b , 1 } ;";
ASSERT_EQUALS(exp, tok(code));
}
};
REGISTER_TEST(TestSimplifyTokens)