Merge branch 'master' of git@github.com:danmar/cppcheck

This commit is contained in:
Vesa Pikki 2009-05-24 12:10:10 +03:00
commit d53eb9e303
5 changed files with 95 additions and 8 deletions

View File

@ -116,6 +116,9 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetAllocationType(const To
if (Token::simpleMatch(tok2, "popen (")) if (Token::simpleMatch(tok2, "popen ("))
return Pipe; return Pipe;
if (Token::Match(tok2, "opendir|fdopendir ("))
return Dir;
// Userdefined allocation function.. // Userdefined allocation function..
std::list<AllocFunc>::const_iterator it = _listAllocFunc.begin(); std::list<AllocFunc>::const_iterator it = _listAllocFunc.begin();
while (it != _listAllocFunc.end()) while (it != _listAllocFunc.end())
@ -181,9 +184,7 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType(const
if (Token::simpleMatch(tok, std::string("free ( " + names + " ) ;").c_str()) || if (Token::simpleMatch(tok, std::string("free ( " + names + " ) ;").c_str()) ||
Token::simpleMatch(tok, std::string("kfree ( " + names + " ) ;").c_str())) Token::simpleMatch(tok, std::string("kfree ( " + names + " ) ;").c_str()))
{
return Malloc; return Malloc;
}
if (Token::simpleMatch(tok, std::string("g_free ( " + names + " ) ;").c_str())) if (Token::simpleMatch(tok, std::string("g_free ( " + names + " ) ;").c_str()))
return gMalloc; return gMalloc;
@ -195,6 +196,9 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType(const
if (Token::simpleMatch(tok, std::string("pclose ( " + names + " )").c_str())) if (Token::simpleMatch(tok, std::string("pclose ( " + names + " )").c_str()))
return Pipe; return Pipe;
if (Token::simpleMatch(tok, std::string("closedir ( " + names + " )").c_str()))
return Dir;
return No; return No;
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -219,6 +223,11 @@ const char * CheckMemoryLeakClass::call_func(const Token *tok, std::list<const T
Token::Match(tok, "setvbuf|setbuf|setbuffer|setlinebuf|rewind")) Token::Match(tok, "setvbuf|setbuf|setbuffer|setlinebuf|rewind"))
return 0; 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.. // Convert functions that are not allocating nor deallocating memory..
if (Token::Match(tok, "atoi|atof|atol|strtol|strtoul|strtod")) if (Token::Match(tok, "atoi|atof|atol|strtol|strtoul|strtod"))
return 0; return 0;
@ -308,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) void CheckMemoryLeakClass::MemoryLeak(const Token *tok, const char varname[], AllocType alloctype, bool all)
{ {
if (alloctype == CheckMemoryLeakClass::File || if (alloctype == CheckMemoryLeakClass::File ||
alloctype == CheckMemoryLeakClass::Pipe) alloctype == CheckMemoryLeakClass::Pipe ||
alloctype == CheckMemoryLeakClass::Dir)
resourceLeakError(tok, varname); resourceLeakError(tok, varname);
else if (all) else if (all)
memleakallError(tok, varname); memleakallError(tok, varname);
@ -544,7 +554,7 @@ Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list<const Token *>
if (parlevel <= 0) if (parlevel <= 0)
break; 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("dealloc");
addtoken(";"); addtoken(";");

View File

@ -56,7 +56,7 @@ public:
private: private:
/** What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */ /** 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.. // Extra allocation..
class AllocFunc class AllocFunc

View File

@ -82,7 +82,7 @@ void CheckOther::WarningRedundantCode()
varname1 = tok->strAt(2); varname1 = tok->strAt(2);
tok2 = tok->tokAt(4); tok2 = tok->tokAt(4);
} }
else if (Token::Match(tok, "if ( %var% != NULL )")) else if (Token::Match(tok, "if ( %var% != 0 )"))
{ {
varname1 = tok->strAt(2); varname1 = tok->strAt(2);
tok2 = tok->tokAt(6); tok2 = tok->tokAt(6);
@ -102,7 +102,7 @@ void CheckOther::WarningRedundantCode()
} }
else if (Token::Match(tok2, "delete [ ] %var% ; }")) 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% ) ; }")) else if (Token::Match(tok2, "free ( %var% ) ; }"))
{ {
@ -121,7 +121,7 @@ void CheckOther::WarningRedundantCode()
} }
else if (Token::Match(tok2, "delete [ ] %var% ;")) 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% ) ;")) else if (Token::Match(tok2, "free ( %var% ) ;"))
{ {

View File

@ -217,6 +217,12 @@ private:
TEST_CASE(strndup_function); TEST_CASE(strndup_function);
TEST_CASE(fcloseall_function); TEST_CASE(fcloseall_function);
TEST_CASE(file_functions); 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); TEST_CASE(pointer_to_pointer);
} }
@ -2190,6 +2196,63 @@ private:
ASSERT_EQUALS(std::string(""), errout.str()); 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() void file_functions()
{ {
check("void f()\n" check("void f()\n"

View File

@ -145,6 +145,20 @@ private:
" delete p;\n" " delete p;\n"
"}\n"); "}\n");
ASSERT_EQUALS(std::string("[test.cpp:3]: (style) Redundant condition. It is safe to deallocate a NULL pointer\n"), errout.str()); 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() void unreachable1()