diff --git a/src/checkmemoryleak.cpp b/src/checkmemoryleak.cpp index fe65b980b..6011f47e8 100644 --- a/src/checkmemoryleak.cpp +++ b/src/checkmemoryleak.cpp @@ -116,6 +116,9 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetAllocationType(const To if (Token::simpleMatch(tok2, "popen (")) return Pipe; + if (Token::Match(tok2, "opendir|fdopendir (")) + return Dir; + // Userdefined allocation function.. std::list::const_iterator it = _listAllocFunc.begin(); while (it != _listAllocFunc.end()) @@ -181,9 +184,7 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType(const if (Token::simpleMatch(tok, std::string("free ( " + names + " ) ;").c_str()) || Token::simpleMatch(tok, std::string("kfree ( " + names + " ) ;").c_str())) - { return Malloc; - } if (Token::simpleMatch(tok, std::string("g_free ( " + names + " ) ;").c_str())) return gMalloc; @@ -195,6 +196,9 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType(const if (Token::simpleMatch(tok, std::string("pclose ( " + names + " )").c_str())) return Pipe; + if (Token::simpleMatch(tok, std::string("closedir ( " + names + " )").c_str())) + return Dir; + return No; } //-------------------------------------------------------------------------- @@ -219,6 +223,11 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list if (parlevel <= 0) break; } - if (Token::simpleMatch(tok2, std::string("fclose ( " + varnameStr + " )").c_str())) + if (Token::Match(tok2, std::string("fclose|closedir ( " + varnameStr + " )").c_str())) { addtoken("dealloc"); addtoken(";"); diff --git a/src/checkmemoryleak.h b/src/checkmemoryleak.h index 1d5c72e9a..9ce1729e6 100644 --- a/src/checkmemoryleak.h +++ b/src/checkmemoryleak.h @@ -56,7 +56,7 @@ public: private: /** What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */ - enum AllocType { No, Malloc, gMalloc, New, NewArray, File, Pipe, Many }; + enum AllocType { No, Malloc, gMalloc, New, NewArray, File, Pipe, Dir, Many }; // Extra allocation.. class AllocFunc diff --git a/src/checkother.cpp b/src/checkother.cpp index fc5bde097..2fc7ee54e 100644 --- a/src/checkother.cpp +++ b/src/checkother.cpp @@ -82,7 +82,7 @@ void CheckOther::WarningRedundantCode() varname1 = tok->strAt(2); tok2 = tok->tokAt(4); } - else if (Token::Match(tok, "if ( %var% != NULL )")) + else if (Token::Match(tok, "if ( %var% != 0 )")) { varname1 = tok->strAt(2); tok2 = tok->tokAt(6); @@ -102,7 +102,7 @@ void CheckOther::WarningRedundantCode() } else if (Token::Match(tok2, "delete [ ] %var% ; }")) { - err = (strcmp(tok2->strAt(1), varname1) == 0); + err = (strcmp(tok2->strAt(3), varname1) == 0); } else if (Token::Match(tok2, "free ( %var% ) ; }")) { @@ -121,7 +121,7 @@ void CheckOther::WarningRedundantCode() } else if (Token::Match(tok2, "delete [ ] %var% ;")) { - err = (strcmp(tok2->strAt(1), varname1) == 0); + err = (strcmp(tok2->strAt(3), varname1) == 0); } else if (Token::Match(tok2, "free ( %var% ) ;")) { diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index b5fddb0b0..206c973ad 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -217,6 +217,12 @@ private: TEST_CASE(strndup_function); TEST_CASE(fcloseall_function); TEST_CASE(file_functions); + + TEST_CASE(opendir_function); + TEST_CASE(fdopendir_function); + TEST_CASE(closedir_function); + TEST_CASE(dir_functions); + TEST_CASE(pointer_to_pointer); } @@ -2190,6 +2196,63 @@ private: ASSERT_EQUALS(std::string(""), errout.str()); } + void opendir_function() + { + check("void f()\n" + "{\n" + " DIR *f = opendir(\".\");\n" + "}\n"); + ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Resource leak: f\n"), errout.str()); + } + + void fdopendir_function() + { + check("void f(int fd)\n" + "{\n" + " DIR *f = fdopendir(fd);\n" + "}\n"); + ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Resource leak: f\n"), errout.str()); + } + + void closedir_function() + { + check("void f()\n" + "{\n" + " DIR *f = opendir(\".\");\n" + " closedir(f);\n" + "}\n"); + ASSERT_EQUALS(std::string(""), errout.str()); + + check("void f(int fd)\n" + "{\n" + " DIR *f = fdopendir(fd);\n" + " closedir(f);\n" + "}\n"); + ASSERT_EQUALS(std::string(""), errout.str()); + + check("void foo()\n" + "{\n" + " DIR * f = opendir(dirname);\n" + " if (closedir(f));\n" + "}\n"); + ASSERT_EQUALS(std::string(""), errout.str()); + } + + void dir_functions() + { + check("void f()\n" + "{\n" + " DIR *f = opendir(dir);\n" + " readdir(f);\n;" + " readdir_r(f, entry, res);\n;" + " rewinddir(f);\n;" + " telldir(f);\n;" + " seekdir(f, 2)\n;" + " scandir(f, namelist, filter, comp);\n;" + "}\n"); + ASSERT_EQUALS(std::string("[test.cpp:10]: (error) Resource leak: f\n"), errout.str()); + } + void file_functions() { check("void f()\n" diff --git a/test/testother.cpp b/test/testother.cpp index 6b5381d76..5cc7adce4 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -145,6 +145,20 @@ private: " delete p;\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer\n"), errout.str()); + + check("void foo()\n" + "{\n" + " if (p != NULL)\n" + " delete p;\n" + "}\n"); + ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer\n"), errout.str()); + + check("void foo()\n" + "{\n" + " if (p)\n" + " delete [] p;\n" + "}\n"); + ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer\n"), errout.str()); } void unreachable1()