Fixed #9795 (False positive: Local lock is not ineffective, mutex is locked in thread also.)
This commit is contained in:
parent
5fa3d5304b
commit
27841d6b81
|
@ -2394,25 +2394,12 @@ void CheckStl::useStlAlgorithm()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isMutex(const Variable* var)
|
|
||||||
{
|
|
||||||
const Token* tok = Token::typeDecl(var->nameToken()).first;
|
|
||||||
return Token::Match(tok, "std :: mutex|recursive_mutex|timed_mutex|recursive_timed_mutex|shared_mutex");
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isLockGuard(const Variable* var)
|
static bool isLockGuard(const Variable* var)
|
||||||
{
|
{
|
||||||
const Token* tok = Token::typeDecl(var->nameToken()).first;
|
const Token* tok = Token::typeDecl(var->nameToken()).first;
|
||||||
return Token::Match(tok, "std :: lock_guard|unique_lock|scoped_lock");
|
return Token::Match(tok, "std :: lock_guard|unique_lock|scoped_lock");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isLocalMutex(const Variable* var, const Scope* scope)
|
|
||||||
{
|
|
||||||
if (!var)
|
|
||||||
return false;
|
|
||||||
return !var->isReference() && !var->isRValueReference() && !var->isStatic() && var->scope() == scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckStl::globalLockGuardError(const Token* tok)
|
void CheckStl::globalLockGuardError(const Token* tok)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::warning,
|
reportError(tok, Severity::warning,
|
||||||
|
@ -2420,13 +2407,6 @@ void CheckStl::globalLockGuardError(const Token* tok)
|
||||||
"Lock guard is defined globally. Lock guards are intended to be local. A global lock guard could lead to a deadlock since it won't unlock until the end of the program.", CWE833, false);
|
"Lock guard is defined globally. Lock guards are intended to be local. A global lock guard could lead to a deadlock since it won't unlock until the end of the program.", CWE833, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckStl::localMutexError(const Token* tok)
|
|
||||||
{
|
|
||||||
reportError(tok, Severity::warning,
|
|
||||||
"localMutex",
|
|
||||||
"The lock is ineffective because the mutex is locked at the same scope as the mutex itself.", CWE667, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckStl::checkMutexes()
|
void CheckStl::checkMutexes()
|
||||||
{
|
{
|
||||||
for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) {
|
for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) {
|
||||||
|
@ -2434,19 +2414,12 @@ void CheckStl::checkMutexes()
|
||||||
const Variable* var = tok->variable();
|
const Variable* var = tok->variable();
|
||||||
if (!var)
|
if (!var)
|
||||||
continue;
|
continue;
|
||||||
if (Token::Match(tok, "%var% . lock ( )")) {
|
if (Token::Match(tok, "%var% (|{ %var% )|}|,")) {
|
||||||
if (!isMutex(var))
|
|
||||||
continue;
|
|
||||||
if (isLocalMutex(var, tok->scope()))
|
|
||||||
localMutexError(tok);
|
|
||||||
} else if (Token::Match(tok, "%var% (|{ %var% )|}|,")) {
|
|
||||||
if (!isLockGuard(var))
|
if (!isLockGuard(var))
|
||||||
continue;
|
continue;
|
||||||
const Variable* mvar = tok->tokAt(2)->variable();
|
const Variable* mvar = tok->tokAt(2)->variable();
|
||||||
if (var->isStatic() || var->isGlobal())
|
if (var->isStatic() || var->isGlobal())
|
||||||
globalLockGuardError(tok);
|
globalLockGuardError(tok);
|
||||||
else if (isLocalMutex(mvar, tok->scope()))
|
|
||||||
localMutexError(tok);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,7 +233,6 @@ private:
|
||||||
void useStlAlgorithmError(const Token *tok, const std::string &algoName);
|
void useStlAlgorithmError(const Token *tok, const std::string &algoName);
|
||||||
|
|
||||||
void globalLockGuardError(const Token *tok);
|
void globalLockGuardError(const Token *tok);
|
||||||
void localMutexError(const Token *tok);
|
|
||||||
|
|
||||||
void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const OVERRIDE {
|
void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const OVERRIDE {
|
||||||
ErrorPath errorPath;
|
ErrorPath errorPath;
|
||||||
|
@ -272,7 +271,6 @@ private:
|
||||||
c.readingEmptyStlContainerError(nullptr);
|
c.readingEmptyStlContainerError(nullptr);
|
||||||
c.useStlAlgorithmError(nullptr, "");
|
c.useStlAlgorithmError(nullptr, "");
|
||||||
c.globalLockGuardError(nullptr);
|
c.globalLockGuardError(nullptr);
|
||||||
c.localMutexError(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string myName() {
|
static std::string myName() {
|
||||||
|
|
|
@ -4445,28 +4445,6 @@ private:
|
||||||
true);
|
true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" std::mutex m;\n"
|
|
||||||
" std::lock_guard<std::mutex> g(m);\n"
|
|
||||||
"}\n",
|
|
||||||
true);
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" std::mutex m;\n"
|
|
||||||
" std::unique_lock<std::mutex> g(m);\n"
|
|
||||||
"}\n",
|
|
||||||
true);
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself.\n", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
" std::mutex m;\n"
|
|
||||||
" std::unique_lock<std::mutex> g(m, std::defer_lock);\n"
|
|
||||||
" std::lock(g);\n"
|
|
||||||
"}\n",
|
|
||||||
true);
|
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself.\n", errout.str());
|
|
||||||
|
|
||||||
check("void g();\n"
|
check("void g();\n"
|
||||||
"void f() {\n"
|
"void f() {\n"
|
||||||
" static std::mutex m;\n"
|
" static std::mutex m;\n"
|
||||||
|
@ -4477,16 +4455,6 @@ private:
|
||||||
true);
|
true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void g();\n"
|
|
||||||
"void f() {\n"
|
|
||||||
" std::mutex m;\n"
|
|
||||||
" m.lock();\n"
|
|
||||||
" g();\n"
|
|
||||||
" m.unlock();\n"
|
|
||||||
"}\n",
|
|
||||||
true);
|
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself.\n", errout.str());
|
|
||||||
|
|
||||||
check("class A {\n"
|
check("class A {\n"
|
||||||
" std::mutex m;\n"
|
" std::mutex m;\n"
|
||||||
" void f() {\n"
|
" void f() {\n"
|
||||||
|
@ -4535,25 +4503,6 @@ private:
|
||||||
"}\n",
|
"}\n",
|
||||||
true);
|
true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("std::mutex& h();\n"
|
|
||||||
"void f() {\n"
|
|
||||||
" auto m = h();\n"
|
|
||||||
" std::lock_guard<std::mutex> g(m);\n"
|
|
||||||
"}\n",
|
|
||||||
true);
|
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself.\n", errout.str());
|
|
||||||
|
|
||||||
check("void g();\n"
|
|
||||||
"std::mutex& h();\n"
|
|
||||||
"void f() {\n"
|
|
||||||
" auto m = h();\n"
|
|
||||||
" m.lock();\n"
|
|
||||||
" g();\n"
|
|
||||||
" m.unlock();\n"
|
|
||||||
"}\n",
|
|
||||||
true);
|
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (warning) The lock is ineffective because the mutex is locked at the same scope as the mutex itself.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue