Take symbol database into use or improve its usage in some checks.
This commit is contained in:
parent
9b685ba3c3
commit
91a0a071d0
|
@ -1747,7 +1747,13 @@ void CheckBufferOverrun::checkBufferAllocatedWithStrlen()
|
|||
void CheckBufferOverrun::checkInsecureCmdLineArgs()
|
||||
{
|
||||
const char pattern[] = "main ( int %var% , char *";
|
||||
for (const Token *tok = Token::findmatch(_tokenizer->tokens(), pattern); tok; tok = Token::findmatch(tok->next(),pattern)) {
|
||||
|
||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
for (std::list<Function>::const_iterator j = i->functionList.begin(); j != i->functionList.end(); ++j) {
|
||||
const Token* tok = j->token;
|
||||
|
||||
// Get the name of the argv variable
|
||||
unsigned int varid = 0;
|
||||
if (Token::Match(tok, "main ( int %var% , char * %var% [ ] ,|)")) {
|
||||
|
@ -1796,7 +1802,7 @@ void CheckBufferOverrun::checkInsecureCmdLineArgs()
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -288,13 +288,15 @@ bool CheckNullPointer::isPointer(const unsigned int varid)
|
|||
|
||||
void CheckNullPointer::nullPointerAfterLoop()
|
||||
{
|
||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
// Locate insufficient null-pointer handling after loop
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
// only interested in while ( %var% )
|
||||
// TODO: Aren't there false negatives. Shouldn't other loops be handled such as:
|
||||
// - while ( ! %var% )
|
||||
// - while ( %var% && .. )
|
||||
if (! Token::Match(tok, "while ( %var% )|&&"))
|
||||
const Token* const tok = i->classDef;
|
||||
if (i->type != Scope::eWhile || !Token::Match(tok, "while ( %var% )|&&"))
|
||||
continue;
|
||||
|
||||
// Get variable id for the loop variable
|
||||
|
@ -363,15 +365,18 @@ void CheckNullPointer::nullPointerAfterLoop()
|
|||
|
||||
void CheckNullPointer::nullPointerLinkedList()
|
||||
{
|
||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
// looping through items in a linked list in a inner loop.
|
||||
// Here is an example:
|
||||
// for (const Token *tok = tokens; tok; tok = tok->next) {
|
||||
// if (tok->str() == "hello")
|
||||
// tok = tok->next; // <- tok might become a null pointer!
|
||||
// }
|
||||
for (const Token *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next()) {
|
||||
// search for a "for" token..
|
||||
if (tok1->str() != "for")
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
const Token* const tok1 = i->classDef;
|
||||
// search for a "for" scope..
|
||||
if (i->type != Scope::eFor || !tok1)
|
||||
continue;
|
||||
|
||||
// is there any dereferencing occurring in the for statement
|
||||
|
@ -624,11 +629,12 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
|||
// Dereferencing a pointer and then checking if it's NULL..
|
||||
// This check will first scan for the check. And then scan backwards
|
||||
// from the check, searching for dereferencing.
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
// TODO: false negatives.
|
||||
// - logical operators
|
||||
// - while
|
||||
if (tok->str() == "if" && Token::Match(tok->previous(), "; if ( !| %var% )|%oror%|&&")) {
|
||||
const Token* const tok = i->classDef;
|
||||
if (i->type == Scope::eIf && tok && Token::Match(tok->previous(), "; if ( !| %var% )|%oror%|&&")) {
|
||||
const Token * vartok = tok->tokAt(2);
|
||||
if (vartok->str() == "!")
|
||||
vartok = vartok->next();
|
||||
|
|
|
@ -249,12 +249,15 @@ void CheckOther::checkSuspiciousSemicolon()
|
|||
if (!_settings->inconclusive || !_settings->isEnabled("style"))
|
||||
return;
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
// Look for "if(); {}", "for(); {}" or "while(); {}"
|
||||
if (Token::Match(tok, "if|for|while (")) {
|
||||
const Token *end = tok->next()->link();
|
||||
if (!end)
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
if (i->type == Scope::eIf || i->type == Scope::eElse || i->type == Scope::eElseIf || i->type == Scope::eWhile || i->type == Scope::eFor) {
|
||||
const Token *tok = Token::findsimplematch(i->classDef, "(", i->classEnd);
|
||||
if (!tok)
|
||||
continue;
|
||||
const Token *end = tok->link();
|
||||
|
||||
// Ensure the semicolon is at the same line number as the if/for/while statement
|
||||
// and the {..} block follows it without an extra empty line.
|
||||
|
@ -580,13 +583,14 @@ void CheckOther::checkSwitchCaseFallThrough()
|
|||
if (!(_settings->isEnabled("style") && _settings->experimental))
|
||||
return;
|
||||
|
||||
const char switchPattern[] = "switch (";
|
||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
const char breakPattern[] = "break|continue|return|exit|goto|throw";
|
||||
|
||||
// Find the beginning of a switch. E.g.:
|
||||
// switch (var) { ...
|
||||
const Token *tok = Token::findmatch(_tokenizer->tokens(), switchPattern);
|
||||
while (tok) {
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
const Token* const tok = i->classDef;
|
||||
if (i->type != Scope::eSwitch || !tok) // Find the beginning of a switch
|
||||
continue;
|
||||
|
||||
// Check the contents of the switch statement
|
||||
std::stack<std::pair<Token *, bool> > ifnest;
|
||||
|
@ -638,7 +642,7 @@ void CheckOther::checkSwitchCaseFallThrough()
|
|||
}
|
||||
loopnest.push(tok2->link());
|
||||
justbreak = false;
|
||||
} else if (Token::Match(tok2, switchPattern)) {
|
||||
} else if (Token::simpleMatch(tok2, "switch (")) {
|
||||
// skip over nested switch, we'll come to that soon
|
||||
tok2 = tok2->next()->link()->next()->link();
|
||||
} else if (Token::Match(tok2, breakPattern)) {
|
||||
|
@ -699,8 +703,6 @@ void CheckOther::checkSwitchCaseFallThrough()
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
tok = Token::findmatch(tok->next(), switchPattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2290,17 +2292,12 @@ void CheckOther::checkDuplicateIf()
|
|||
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
std::list<Scope>::const_iterator scope;
|
||||
|
||||
for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
// only check functions
|
||||
if (scope->type != Scope::eFunction)
|
||||
for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
const Token* const tok = scope->classDef;
|
||||
// only check if statements
|
||||
if (scope->type != Scope::eIf || !tok)
|
||||
continue;
|
||||
|
||||
// check all the code in the function for if (...) and else if (...) statements
|
||||
for (const Token *tok = scope->classStart; tok && tok != scope->classStart->link(); tok = tok->next()) {
|
||||
if (Token::simpleMatch(tok, "if (") && tok->strAt(-1) != "else" &&
|
||||
Token::simpleMatch(tok->next()->link(), ") {")) {
|
||||
std::map<std::string, const Token*> expressionMap;
|
||||
|
||||
// get the expression from the token stream
|
||||
|
@ -2335,10 +2332,6 @@ void CheckOther::checkDuplicateIf()
|
|||
// find the next else if (...) statement
|
||||
tok1 = tok1->linkAt(3)->next()->link();
|
||||
}
|
||||
|
||||
tok = tok->next()->link()->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2371,13 +2364,10 @@ void CheckOther::checkDuplicateBranch()
|
|||
std::list<Scope>::const_iterator scope;
|
||||
|
||||
for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
// only check functions
|
||||
if (scope->type != Scope::eFunction)
|
||||
continue;
|
||||
const Token* const tok = scope->classDef;
|
||||
|
||||
// check all the code in the function for if (..) else
|
||||
for (const Token *tok = scope->classStart; tok && tok != scope->classStart->link(); tok = tok->next()) {
|
||||
if (Token::simpleMatch(tok, "if (") && tok->strAt(-1) != "else" &&
|
||||
if (scope->type == Scope::eIf && tok && tok->next() &&
|
||||
Token::simpleMatch(tok->next()->link(), ") {") &&
|
||||
Token::simpleMatch(tok->next()->link()->next()->link(), "} else {")) {
|
||||
// save if branch code
|
||||
|
@ -2392,9 +2382,6 @@ void CheckOther::checkDuplicateBranch()
|
|||
// check for duplicates
|
||||
if (branch1 == branch2)
|
||||
duplicateBranchError(tok, tok1->tokAt(2));
|
||||
|
||||
tok = tok->next()->link()->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,10 +238,13 @@ void CheckStl::mismatchingContainers()
|
|||
|
||||
void CheckStl::stlOutOfBounds()
|
||||
{
|
||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
// Scan through all tokens..
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
const Token* const tok = i->classDef;
|
||||
// only interested in "for" loops
|
||||
if (!Token::simpleMatch(tok, "for ("))
|
||||
if (i->type != Scope::eFor || !tok)
|
||||
continue;
|
||||
|
||||
// check if the for loop condition is wrong
|
||||
|
@ -432,13 +435,16 @@ private:
|
|||
|
||||
void CheckStl::erase()
|
||||
{
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::simpleMatch(tok, "for (")) {
|
||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
const Token* const tok = i->classDef;
|
||||
|
||||
if (tok && i->type == Scope::eFor) {
|
||||
for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) {
|
||||
if (tok2->str() == ";") {
|
||||
if (Token::Match(tok2, "; %var% !=")) {
|
||||
// Get declaration token for var..
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const Variable *variableInfo = symbolDatabase->getVariableFromVarId(tok2->next()->varId());
|
||||
const Token *decltok = variableInfo ? variableInfo->typeEndToken() : NULL;
|
||||
|
||||
|
@ -463,7 +469,7 @@ void CheckStl::erase()
|
|||
}
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "while ( %var% !=")) {
|
||||
else if (i->type == Scope::eWhile && Token::Match(tok, "while ( %var% !=")) {
|
||||
const unsigned int varid = tok->tokAt(2)->varId();
|
||||
if (varid > 0 && Token::findmatch(_tokenizer->tokens(), "> :: iterator %varid%", varid))
|
||||
EraseCheckLoop::checkScope(this, tok->tokAt(2));
|
||||
|
@ -712,7 +718,12 @@ void CheckStl::if_find()
|
|||
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
if (i->type != Scope::eIf && i->type != Scope::eElseIf)
|
||||
continue;
|
||||
|
||||
const Token* tok = i->classDef;
|
||||
|
||||
if (Token::Match(tok, "if ( !| %var% . find ( %any% ) )")) {
|
||||
// goto %var%
|
||||
tok = tok->tokAt(2);
|
||||
|
@ -738,7 +749,7 @@ void CheckStl::if_find()
|
|||
}
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "if ( !| std :: find|find_if (")) {
|
||||
else if (Token::Match(tok, "if ( !| std :: find|find_if (")) {
|
||||
// goto '(' for the find
|
||||
tok = tok->tokAt(4);
|
||||
if (tok->isName())
|
||||
|
|
|
@ -442,22 +442,14 @@ private:
|
|||
void erase1() {
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" for (it = foo.begin(); it != foo.end(); ++it)\n"
|
||||
" {\n"
|
||||
" for (it = foo.begin(); it != foo.end(); ++it) {\n"
|
||||
" foo.erase(it);\n"
|
||||
" }\n"
|
||||
" for (it = foo.begin(); it != foo.end(); ++it) {\n"
|
||||
" foo.erase(it);\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:5]: (error) Dangerous iterator usage after erase()-method.\n", errout.str());
|
||||
|
||||
check("for (it = foo.begin(); it != foo.end(); ++it)\n"
|
||||
"{\n"
|
||||
" foo.erase(it);\n"
|
||||
"}\n"
|
||||
"for (it = foo.begin(); it != foo.end(); ++it)\n"
|
||||
"{\n"
|
||||
" foo.erase(it);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Dangerous iterator usage after erase()-method.\n"
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Dangerous iterator usage after erase()-method.\n"
|
||||
"[test.cpp:7]: (error) Dangerous iterator usage after erase()-method.\n", errout.str());
|
||||
|
||||
check("void f(std::list<int> &ints)\n"
|
||||
|
|
Loading…
Reference in New Issue