Added support to search resource leaks after opendir()/fdopendir() usage.

This commit is contained in:
Slava Semushin 2009-05-22 14:24:03 +07:00
parent f5300ae56c
commit 2654a4aa54
3 changed files with 78 additions and 3 deletions

View File

@ -116,6 +116,9 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetAllocationType(const To
if (Token::simpleMatch(tok2, "popen ("))
return Pipe;
if (Token::simpleMatch(tok2, "opendir (") || Token::simpleMatch(tok2, "fdopendir ("))
return Dir;
// Userdefined allocation function..
std::list<AllocFunc>::const_iterator it = _listAllocFunc.begin();
while (it != _listAllocFunc.end())
@ -193,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;
}
//--------------------------------------------------------------------------
@ -217,6 +223,11 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const T
Token::Match(tok, "setvbuf|setbuf|setbuffer|setlinebuf|rewind"))
return 0;
// Functions to work with directories that are not allocating nor
// deallocating memory..
if (Token::Match(tok, "readdir|readdir_r|rewinddir|telldir|seekdir|scandir"))
return 0;
// Convert functions that are not allocating nor deallocating memory..
if (Token::Match(tok, "atoi|atof|atol|strtol|strtoul|strtod"))
return 0;
@ -306,7 +317,8 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const T
void CheckMemoryLeakClass::MemoryLeak(const Token *tok, const char varname[], AllocType alloctype, bool all)
{
if (alloctype == CheckMemoryLeakClass::File ||
alloctype == CheckMemoryLeakClass::Pipe)
alloctype == CheckMemoryLeakClass::Pipe ||
alloctype == CheckMemoryLeakClass::Dir)
resourceLeakError(tok, varname);
else if (all)
memleakallError(tok, varname);
@ -542,7 +554,7 @@ Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list<const Token *>
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(";");

View File

@ -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

View File

@ -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"