Fixed #3162: Check whole condition for suspicious find calls.
This commit is contained in:
parent
ecc5dea113
commit
77d9ed1877
|
@ -722,19 +722,27 @@ void CheckStl::if_find()
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||||
if ((i->type != Scope::eIf && i->type != Scope::eElseIf) || !i->classDef)
|
if ((i->type != Scope::eIf && i->type != Scope::eElseIf && i->type != Scope::eWhile) || !i->classDef)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token* tok = i->classDef->next();
|
const Token* tok = i->classDef->next();
|
||||||
if (tok->str() == "if")
|
if (tok->str() == "if")
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
if (Token::Match(tok, "( !| %var% . find (")) {
|
for (const Token* const end = tok->link(); tok != end; tok = tok->next()) {
|
||||||
// goto %var%
|
if (Token::Match(tok, "&&|(|%oror%"))
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
while (tok->str() == "(")
|
||||||
|
tok = tok->next();
|
||||||
|
|
||||||
if (tok->str() == "!")
|
if (tok->str() == "!")
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
if (!Token::simpleMatch(tok->linkAt(3), ") )"))
|
|
||||||
|
if (Token::Match(tok, "%var% . find (")) {
|
||||||
|
if (!Token::Match(tok->linkAt(3), ") &&|)|%oror%"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const unsigned int varid = tok->varId();
|
const unsigned int varid = tok->varId();
|
||||||
|
@ -754,28 +762,20 @@ void CheckStl::if_find()
|
||||||
}
|
}
|
||||||
|
|
||||||
//check also for vector-like or pointer containers
|
//check also for vector-like or pointer containers
|
||||||
else if (Token::Match(tok, "( !| * %var%") || Token::Match(tok, "( !| %var% [")) {
|
else if (Token::Match(tok, "* %var%") || Token::Match(tok, "%var% [")) {
|
||||||
|
// goto %var%
|
||||||
|
if (tok->str() == "*")
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
const Token *tok2 = tok;
|
const Token *tok2 = tok->next();
|
||||||
if (tok2->str() == "!")
|
|
||||||
tok2 = tok2->next();
|
|
||||||
tok2 = tok2->next();
|
|
||||||
if (tok2->str() == "[")
|
if (tok2->str() == "[")
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link()->next();
|
||||||
tok2 = tok2->next();
|
|
||||||
|
|
||||||
if (!Token::simpleMatch(tok2, ". find ("))
|
if (!Token::simpleMatch(tok2, ". find ("))
|
||||||
continue;
|
continue;
|
||||||
if (!Token::simpleMatch(tok2->linkAt(2), ") )"))
|
if (!Token::Match(tok2->linkAt(2), ") &&|)|%oror%"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// goto %var%
|
|
||||||
if (tok->str() == "!")
|
|
||||||
tok = tok->next();
|
|
||||||
if (tok->str() == "*")
|
|
||||||
tok = tok->next();
|
|
||||||
|
|
||||||
const unsigned int varid = tok->varId();
|
const unsigned int varid = tok->varId();
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
|
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
|
||||||
if (var) {
|
if (var) {
|
||||||
|
@ -795,7 +795,7 @@ void CheckStl::if_find()
|
||||||
if (Token::Match(decl, "%var% <")) {
|
if (Token::Match(decl, "%var% <")) {
|
||||||
decl = decl->tokAt(2);
|
decl = decl->tokAt(2);
|
||||||
//stl-like
|
//stl-like
|
||||||
if (Token::Match(decl, "std :: %var% < %type% >| >>|> &| %varid%", varid))
|
if (Token::Match(decl, "std :: %var% < %type% > > &| %varid%", varid))
|
||||||
if_findError(tok, false);
|
if_findError(tok, false);
|
||||||
//not stl-like, then let's hope it's a pointer or an array
|
//not stl-like, then let's hope it's a pointer or an array
|
||||||
else if (Token::Match(decl, "%type% >")) {
|
else if (Token::Match(decl, "%type% >")) {
|
||||||
|
@ -818,19 +818,15 @@ void CheckStl::if_find()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(tok, "( !| std :: find|find_if (")) {
|
else if (Token::Match(tok, "std :: find|find_if (")) {
|
||||||
// goto '(' for the find
|
|
||||||
tok = tok->tokAt(3);
|
|
||||||
if (tok->str() != "(")
|
|
||||||
tok = tok->next();
|
|
||||||
|
|
||||||
// check that result is checked properly
|
// check that result is checked properly
|
||||||
if (Token::simpleMatch(tok->link(), ") )")) {
|
if (Token::Match(tok->linkAt(3), ") &&|)|%oror%")) {
|
||||||
if_findError(tok, false);
|
if_findError(tok, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CheckStl::if_findError(const Token *tok, bool str)
|
void CheckStl::if_findError(const Token *tok, bool str)
|
||||||
|
|
|
@ -1239,6 +1239,13 @@ private:
|
||||||
" if (s[0].find(\"abc\")) { }\n"
|
" if (s[0].find(\"abc\")) { }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Suspicious checking of string::find() return value.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (warning) Suspicious checking of string::find() return value.\n", errout.str());
|
||||||
|
|
||||||
|
// #3162
|
||||||
|
check("void f(const std::string& s1, const std::string& s2)\n"
|
||||||
|
"{\n"
|
||||||
|
" if ((!s1.empty()) && (0 == s1.find(s2))) { }\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) Suspicious checking of string::find() return value.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue