Refactorization: Avoid iterations over whole token list, limited several checks to function scopes.
This commit is contained in:
parent
5bc775e43e
commit
662283cab8
|
@ -172,7 +172,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2,
|
||||||
return No;
|
return No;
|
||||||
|
|
||||||
// is there a user function with this name?
|
// is there a user function with this name?
|
||||||
if (tokenizer && Token::findmatch(tokenizer->tokens(), ("%type% *|&| " + tok2->str()).c_str()))
|
if (tok2->function())
|
||||||
return No;
|
return No;
|
||||||
return Fd;
|
return Fd;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "checknonreentrantfunctions.h"
|
#include "checknonreentrantfunctions.h"
|
||||||
|
#include "symboldatabase.h"
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -35,21 +36,24 @@ void CheckNonReentrantFunctions::nonReentrantFunctions()
|
||||||
if (!_settings->standards.posix || !_settings->isEnabled("portability"))
|
if (!_settings->standards.posix || !_settings->isEnabled("portability"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::map<std::string,std::string>::const_iterator nonReentrant_end = _nonReentrantFunctions.end();
|
const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token *tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
// Look for function invocations
|
// Look for function invocations
|
||||||
if (!tok->isName() || tok->strAt(1) != "(" || tok->varId() != 0)
|
if (tok->varId() != 0 || !tok->isName() || tok->strAt(1) != "(")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check for non-reentrant function name
|
// Check for non-reentrant function name
|
||||||
std::map<std::string,std::string>::const_iterator it = _nonReentrantFunctions.find(tok->str());
|
std::map<std::string, std::string>::const_iterator it = _nonReentrantFunctions.find(tok->str());
|
||||||
if (it == nonReentrant_end)
|
if (it == _nonReentrantFunctions.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token *prev = tok->previous();
|
const Token *prev = tok->previous();
|
||||||
if (prev) {
|
if (prev) {
|
||||||
// Ignore function definitions, class members or class definitions
|
// Ignore function definitions, class members or class definitions
|
||||||
if (prev->isName() || Token::Match(prev, ".|:"))
|
if (prev->str() == ".")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check for "std" or global namespace, ignore other namespaces
|
// Check for "std" or global namespace, ignore other namespaces
|
||||||
|
@ -58,7 +62,8 @@ void CheckNonReentrantFunctions::nonReentrantFunctions()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only affecting multi threaded code, therefore this is "portability"
|
// Only affecting multi threaded code, therefore this is "portability"
|
||||||
reportError(tok, Severity::portability, "nonreentrantFunctions"+it->first, it->second);
|
reportError(tok, Severity::portability, "nonreentrantFunctions" + it->first, it->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -998,8 +998,11 @@ void CheckOther::checkSuspiciousEqualityComparison()
|
||||||
if (!_settings->isEnabled("warning") || !_settings->inconclusive)
|
if (!_settings->isEnabled("warning") || !_settings->inconclusive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "for (")) {
|
if (Token::simpleMatch(tok, "for (")) {
|
||||||
const Token* const openParen = tok->next();
|
const Token* const openParen = tok->next();
|
||||||
const Token* const closeParen = tok->linkAt(1);
|
const Token* const closeParen = tok->linkAt(1);
|
||||||
|
@ -1039,6 +1042,7 @@ void CheckOther::checkSuspiciousEqualityComparison()
|
||||||
suspiciousEqualityComparisonError(tok->next());
|
suspiciousEqualityComparisonError(tok->next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckOther::suspiciousEqualityComparisonError(const Token* tok)
|
void CheckOther::suspiciousEqualityComparisonError(const Token* tok)
|
||||||
|
@ -2027,7 +2031,12 @@ void CheckOther::duplicateBranchError(const Token *tok1, const Token *tok2)
|
||||||
void CheckOther::checkInvalidFree()
|
void CheckOther::checkInvalidFree()
|
||||||
{
|
{
|
||||||
std::map<unsigned int, bool> allocatedVariables;
|
std::map<unsigned int, bool> allocatedVariables;
|
||||||
for (const Token* tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
|
||||||
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
|
||||||
// Keep track of which variables were assigned addresses to newly-allocated memory
|
// Keep track of which variables were assigned addresses to newly-allocated memory
|
||||||
if (Token::Match(tok, "%var% = malloc|g_malloc|new")) {
|
if (Token::Match(tok, "%var% = malloc|g_malloc|new")) {
|
||||||
|
@ -2082,6 +2091,7 @@ void CheckOther::checkInvalidFree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckOther::invalidFreeError(const Token *tok, bool inconclusive)
|
void CheckOther::invalidFreeError(const Token *tok, bool inconclusive)
|
||||||
|
@ -2099,7 +2109,11 @@ void CheckOther::checkDoubleFree()
|
||||||
std::set<unsigned int> freedVariables;
|
std::set<unsigned int> freedVariables;
|
||||||
std::set<unsigned int> closeDirVariables;
|
std::set<unsigned int> closeDirVariables;
|
||||||
|
|
||||||
for (const Token* tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
// Keep track of any variables passed to "free()", "g_free()" or "closedir()",
|
// Keep track of any variables passed to "free()", "g_free()" or "closedir()",
|
||||||
// and report an error if the same variable is passed twice.
|
// and report an error if the same variable is passed twice.
|
||||||
if (Token::Match(tok, "free|g_free|closedir ( %var% )")) {
|
if (Token::Match(tok, "free|g_free|closedir ( %var% )")) {
|
||||||
|
@ -2187,6 +2201,7 @@ void CheckOther::checkDoubleFree()
|
||||||
closeDirVariables.clear();
|
closeDirVariables.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckOther::doubleFreeError(const Token *tok, const std::string &varname)
|
void CheckOther::doubleFreeError(const Token *tok, const std::string &varname)
|
||||||
|
@ -2375,10 +2390,16 @@ void CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token* to
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CheckOther::redundantGetAndSetUserId()
|
void CheckOther::redundantGetAndSetUserId()
|
||||||
{
|
{
|
||||||
if (_settings->isEnabled("warning")
|
if (!_settings->standards.posix || !_settings->isEnabled("warning"))
|
||||||
&& _settings->standards.posix) {
|
return;
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
// check all the code in the function
|
||||||
|
for (const Token *tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "setuid ( getuid ( ) )")
|
if (Token::simpleMatch(tok, "setuid ( getuid ( ) )")
|
||||||
|| Token::simpleMatch(tok, "seteuid ( geteuid ( ) )")
|
|| Token::simpleMatch(tok, "seteuid ( geteuid ( ) )")
|
||||||
|| Token::simpleMatch(tok, "setgid ( getgid ( ) )")
|
|| Token::simpleMatch(tok, "setgid ( getgid ( ) )")
|
||||||
|
|
|
@ -270,7 +270,11 @@ void CheckString::incorrectStringBooleanError(const Token *tok, const std::strin
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void CheckString::sprintfOverlappingData()
|
void CheckString::sprintfOverlappingData()
|
||||||
{
|
{
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
// Get variable id of target buffer..
|
// Get variable id of target buffer..
|
||||||
unsigned int varid = 0;
|
unsigned int varid = 0;
|
||||||
|
|
||||||
|
@ -300,6 +304,7 @@ void CheckString::sprintfOverlappingData()
|
||||||
}
|
}
|
||||||
} while (nullptr != (tok2 = tok2->nextArgument()));
|
} while (nullptr != (tok2 = tok2->nextArgument()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckString::sprintfOverlappingDataError(const Token *tok, const std::string &varname)
|
void CheckString::sprintfOverlappingDataError(const Token *tok, const std::string &varname)
|
||||||
|
|
|
@ -3682,20 +3682,20 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void redundantGetAndSetUserId() {
|
void redundantGetAndSetUserId() {
|
||||||
check("seteuid(geteuid());\n", nullptr, false , false, true);
|
check("void foo() { seteuid(geteuid()); }", nullptr, false , false, true);
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
||||||
check("setuid(getuid());\n", nullptr, false , false, true);
|
check("void foo() { setuid(getuid()); }", nullptr, false , false, true);
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
||||||
check("setgid(getgid());\n", nullptr, false , false, true);
|
check("void foo() { setgid(getgid()); }", nullptr, false , false, true);
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
||||||
check("setegid(getegid());\n", nullptr, false , false, true);
|
check("void foo() { setegid(getegid()); }", nullptr, false , false, true);
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (warning) Redundant get and set of user id.\n", errout.str());
|
||||||
|
|
||||||
check("seteuid(getuid());\n", nullptr, false , false, true);
|
check("void foo() { seteuid(getuid()); }", nullptr, false , false, true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
check("seteuid(foo());\n", nullptr, false , false, true);
|
check("void foo() { seteuid(foo()); }", nullptr, false , false, true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
check("foo(getuid());\n", nullptr, false , false, true);
|
check("void foo() { foo(getuid()); }", nullptr, false , false, true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue