From 5800692fa132a5cbdeaf537d200e78c833db07f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 17 Jul 2019 08:59:09 +0200 Subject: [PATCH] Move and refactor the CheckMemoryLeak::isclass --- lib/checkleakautovar.cpp | 25 ++++++++++++++++++++++++- lib/checkmemoryleak.cpp | 20 -------------------- lib/checkmemoryleak.h | 8 -------- test/testleakautovar.cpp | 20 +++++++++++++++++++- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index c2e914c28..60ce8dc8a 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -53,6 +53,29 @@ static const CWE CWE415(415U); static const int NEW_ARRAY = -2; 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() @@ -222,7 +245,7 @@ static bool checkVariable(const Token *varTok, const bool isCpp) if (!var) return false; // Possibly automatically deallocated memory - if (!var->typeStartToken()->isStandardType() && Token::Match(varTok, "%var% = new")) + if (isAutoDealloc(var) && Token::Match(varTok, "%var% = new")) return false; if (!var->isPointer() && !var->typeStartToken()->isStandardType()) return false; diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 4cc10cf46..245065fb9 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -94,26 +94,6 @@ static const std::set 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 *callstack) const { // What we may have... diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index 398b18302..daba457c8 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -114,14 +114,6 @@ public: */ 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) * @param tok token where memory is leaked diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 8aea0b030..610cd966d 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -68,6 +68,8 @@ private: TEST_CASE(assign18); TEST_CASE(assign19); + TEST_CASE(isAutoDealloc); + TEST_CASE(realloc1); TEST_CASE(realloc2); TEST_CASE(realloc3); @@ -93,7 +95,6 @@ private: TEST_CASE(doublefree8); TEST_CASE(doublefree9); - // exit TEST_CASE(exit1); TEST_CASE(exit2); @@ -399,6 +400,23 @@ private: 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() { check("void f() {\n" " void *p = malloc(10);\n"