Move and refactor the CheckMemoryLeak::isclass
This commit is contained in:
parent
8513fb81d2
commit
5800692fa1
|
@ -53,6 +53,29 @@ static const CWE CWE415(415U);
|
||||||
static const int NEW_ARRAY = -2;
|
static const int NEW_ARRAY = -2;
|
||||||
static const int NEW = -1;
|
static const int NEW = -1;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Is variable type some class with automatic deallocation?
|
||||||
|
* @param vartok variable token
|
||||||
|
* @return true unless it can be seen there is no automatic deallocation
|
||||||
|
*/
|
||||||
|
static bool isAutoDealloc(const Variable *var)
|
||||||
|
{
|
||||||
|
if (var->valueType() && var->valueType()->type != ValueType::Type::RECORD && var->valueType()->type != ValueType::Type::UNKNOWN_TYPE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// return false if the type is a simple record type without side effects
|
||||||
|
// a type that has no side effects (no constructors and no members with constructors)
|
||||||
|
/** @todo false negative: check base class for side effects */
|
||||||
|
/** @todo false negative: check constructors for side effects */
|
||||||
|
if (var->typeScope() && var->typeScope()->numConstructors == 0 &&
|
||||||
|
(var->typeScope()->varlist.empty() || var->type()->needInitialization == Type::True) &&
|
||||||
|
var->type()->derivedFrom.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void VarInfo::print()
|
void VarInfo::print()
|
||||||
|
@ -222,7 +245,7 @@ static bool checkVariable(const Token *varTok, const bool isCpp)
|
||||||
if (!var)
|
if (!var)
|
||||||
return false;
|
return false;
|
||||||
// Possibly automatically deallocated memory
|
// Possibly automatically deallocated memory
|
||||||
if (!var->typeStartToken()->isStandardType() && Token::Match(varTok, "%var% = new"))
|
if (isAutoDealloc(var) && Token::Match(varTok, "%var% = new"))
|
||||||
return false;
|
return false;
|
||||||
if (!var->isPointer() && !var->typeStartToken()->isStandardType())
|
if (!var->isPointer() && !var->typeStartToken()->isStandardType())
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -94,26 +94,6 @@ static const std::set<std::string> call_func_white_list = {
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CheckMemoryLeak::isclass(const Token *tok, unsigned int varid) const
|
|
||||||
{
|
|
||||||
if (tok->isStandardType())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const Variable * var = mTokenizer_->getSymbolDatabase()->getVariableFromVarId(varid);
|
|
||||||
|
|
||||||
// return false if the type is a simple record type without side effects
|
|
||||||
// a type that has no side effects (no constructors and no members with constructors)
|
|
||||||
/** @todo false negative: check base class for side effects */
|
|
||||||
/** @todo false negative: check constructors for side effects */
|
|
||||||
if (var && var->typeScope() && var->typeScope()->numConstructors == 0 &&
|
|
||||||
(var->typeScope()->varlist.empty() || var->type()->needInitialization == Type::True) &&
|
|
||||||
var->type()->derivedFrom.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, unsigned int varid, std::list<const Function*> *callstack) const
|
CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, unsigned int varid, std::list<const Function*> *callstack) const
|
||||||
{
|
{
|
||||||
// What we may have...
|
// What we may have...
|
||||||
|
|
|
@ -114,14 +114,6 @@ public:
|
||||||
*/
|
*/
|
||||||
static AllocType getReallocationType(const Token *tok2, unsigned int varid);
|
static AllocType getReallocationType(const Token *tok2, unsigned int varid);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Is a typename the name of a class?
|
|
||||||
* @param tok type token
|
|
||||||
* @param varid variable id
|
|
||||||
* @return true if the type name is the name of a class
|
|
||||||
*/
|
|
||||||
bool isclass(const Token *tok, unsigned int varid) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report that there is a memory leak (new/malloc/etc)
|
* Report that there is a memory leak (new/malloc/etc)
|
||||||
* @param tok token where memory is leaked
|
* @param tok token where memory is leaked
|
||||||
|
|
|
@ -68,6 +68,8 @@ private:
|
||||||
TEST_CASE(assign18);
|
TEST_CASE(assign18);
|
||||||
TEST_CASE(assign19);
|
TEST_CASE(assign19);
|
||||||
|
|
||||||
|
TEST_CASE(isAutoDealloc);
|
||||||
|
|
||||||
TEST_CASE(realloc1);
|
TEST_CASE(realloc1);
|
||||||
TEST_CASE(realloc2);
|
TEST_CASE(realloc2);
|
||||||
TEST_CASE(realloc3);
|
TEST_CASE(realloc3);
|
||||||
|
@ -93,7 +95,6 @@ private:
|
||||||
TEST_CASE(doublefree8);
|
TEST_CASE(doublefree8);
|
||||||
TEST_CASE(doublefree9);
|
TEST_CASE(doublefree9);
|
||||||
|
|
||||||
|
|
||||||
// exit
|
// exit
|
||||||
TEST_CASE(exit1);
|
TEST_CASE(exit1);
|
||||||
TEST_CASE(exit2);
|
TEST_CASE(exit2);
|
||||||
|
@ -399,6 +400,23 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void isAutoDealloc() {
|
||||||
|
check("void f() {\n"
|
||||||
|
" char *p = new char[100];"
|
||||||
|
"}", true);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Memory leak: p\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" Fred *fred = new Fred;"
|
||||||
|
"}", true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" std::string *str = new std::string;"
|
||||||
|
"}", true);
|
||||||
|
TODO_ASSERT_EQUALS("[test.cpp:2]: (error) Memory leak: str\n", "", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void realloc1() {
|
void realloc1() {
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" void *p = malloc(10);\n"
|
" void *p = malloc(10);\n"
|
||||||
|
|
Loading…
Reference in New Issue