2008-12-18 22:28:57 +01:00
/*
2009-01-21 21:04:20 +01:00
* Cppcheck - A tool for static C / C + + code analysis
2010-04-13 21:23:17 +02:00
* Copyright ( C ) 2007 - 2010 Daniel Marjamäki and Cppcheck team .
2008-12-18 22:28:57 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2009-09-27 17:08:31 +02:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2008-12-18 22:28:57 +01:00
*/
2009-10-25 12:49:06 +01:00
# include "tokenize.h"
# include "checkmemoryleak.h"
2008-12-18 22:28:57 +01:00
# include "testsuite.h"
# include <sstream>
extern std : : ostringstream errout ;
2009-06-15 17:44:59 +02:00
2009-12-14 20:30:31 +01:00
class TestLocalLeaks : private TestFixture
{
public :
TestLocalLeaks ( ) : TestFixture ( " TestLocalLeaks " )
{ }
private :
void run ( )
{
TEST_CASE ( test1 ) ;
TEST_CASE ( test2 ) ;
2009-12-20 19:44:32 +01:00
TEST_CASE ( test3 ) ;
TEST_CASE ( test4 ) ;
2010-07-18 15:13:48 +02:00
TEST_CASE ( test5 ) ;
2009-12-14 20:30:31 +01:00
}
void check ( const char code [ ] )
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2009-12-14 20:30:31 +01:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2009-12-14 20:30:31 +01:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . setVarId ( ) ;
tokenizer . simplifyTokenList ( ) ;
// Check for memory leaks..
CheckMemoryLeakInFunction checkMemoryLeak ( & tokenizer , & settings , this ) ;
checkMemoryLeak . localleaks ( ) ;
}
void test1 ( )
{
check ( " void foo() \n "
" { \n "
" char *p = new char[100]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
void test2 ( )
{
check ( " void foo() \n "
" { \n "
" char *p = new char[100]; \n "
" delete [] p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-12-20 19:44:32 +01:00
void test3 ( )
{
check ( " void foo(int x) \n "
" { \n "
" char *p = 0; \n "
" if (x == 1) \n "
" p = new char[100]; \n "
" if (x == 2) \n "
" delete [] p; \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2010-08-05 13:30:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-12-20 19:44:32 +01:00
}
void test4 ( )
{
check ( " void foo(int x) \n "
" { \n "
" char *p = 0; \n "
" if (x == 1) \n "
" p = new char[100]; \n "
" if (x == 1) \n "
" delete [] p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-07-18 15:13:48 +02:00
void test5 ( ) //#ticket 1879
{
check ( " void test() \n "
" { \n "
" int *a = new int[10]; \n "
" try \n "
" { \n "
" } \n "
" catch(...) \n "
" { \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: a \n " , errout . str ( ) ) ;
}
2009-12-14 20:30:31 +01:00
} ;
static TestLocalLeaks testLocalLeaks ;
2009-06-15 17:44:59 +02:00
class TestMemleak : private TestFixture
{
public :
TestMemleak ( ) : TestFixture ( " TestMemleak " )
{ }
private :
void run ( )
{
TEST_CASE ( testFunctionReturnType ) ;
2010-01-26 20:10:52 +01:00
TEST_CASE ( open ) ;
2009-06-15 17:44:59 +02:00
}
CheckMemoryLeak : : AllocType functionReturnType ( const char code [ ] )
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2009-06-15 17:44:59 +02:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2009-06-15 17:44:59 +02:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
2009-08-19 19:42:07 +02:00
tokenizer . setVarId ( ) ;
2009-06-15 17:44:59 +02:00
return ( ( const CheckMemoryLeak * ) 0 ) - > functionReturnType ( tokenizer . tokens ( ) ) ;
}
void testFunctionReturnType ( )
{
{
const char code [ ] = " const char *foo() \n "
" { return 0; } " ;
ASSERT_EQUALS ( CheckMemoryLeak : : No , functionReturnType ( code ) ) ;
}
{
const char code [ ] = " Fred *newFred() \n "
" { return new Fred; } " ;
ASSERT_EQUALS ( CheckMemoryLeak : : New , functionReturnType ( code ) ) ;
}
{
const char code [ ] = " char *foo() \n "
" { return new char[100]; } " ;
ASSERT_EQUALS ( CheckMemoryLeak : : NewArray , functionReturnType ( code ) ) ;
}
2009-06-15 21:13:39 +02:00
{
const char code [ ] = " char *foo() \n "
" { \n "
" char *p = new char[100]; \n "
" return p; \n "
" } " ;
ASSERT_EQUALS ( CheckMemoryLeak : : NewArray , functionReturnType ( code ) ) ;
}
2009-06-15 17:44:59 +02:00
}
2010-01-26 20:10:52 +01:00
void open ( )
{
const char code [ ] = " class A { \n "
" static int open() { \n "
" return 1; \n "
" } \n "
" \n "
" A() { \n "
" int ret = open(); \n "
" } \n "
" }; \n " ;
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
Tokenizer tokenizer ( & settings , this ) ;
2010-01-26 20:10:52 +01:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
// there is no allocation
const Token * tok = Token : : findmatch ( tokenizer . tokens ( ) , " ret = " ) ;
CheckMemoryLeak check ( & tokenizer , 0 ) ;
ASSERT_EQUALS ( CheckMemoryLeak : : No , check . getAllocationType ( tok - > tokAt ( 2 ) , 1 ) ) ;
}
2009-06-15 17:44:59 +02:00
} ;
static TestMemleak testMemleak ;
2009-06-08 20:20:43 +02:00
class TestMemleakInFunction : public TestFixture
2008-12-18 22:28:57 +01:00
{
public :
2009-06-08 20:20:43 +02:00
TestMemleakInFunction ( ) : TestFixture ( " TestMemleakInFunction " )
2008-12-18 22:28:57 +01:00
{ }
private :
2009-01-05 16:49:57 +01:00
void check ( const char code [ ] , bool showAll = false )
2008-12-18 22:28:57 +01:00
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
settings . inconclusive = showAll ;
2008-12-18 22:28:57 +01:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2008-12-18 22:28:57 +01:00
std : : istringstream istr ( code ) ;
2009-01-05 16:49:57 +01:00
tokenizer . tokenize ( istr , " test.cpp " ) ;
2008-12-18 22:28:57 +01:00
tokenizer . setVarId ( ) ;
tokenizer . simplifyTokenList ( ) ;
2010-12-01 18:00:55 +01:00
tokenizer . fillFunctionList ( ) ;
2008-12-18 22:28:57 +01:00
// Check for memory leaks..
2009-06-08 20:20:43 +02:00
CheckMemoryLeakInFunction checkMemoryLeak ( & tokenizer , & settings , this ) ;
2010-08-05 13:30:07 +02:00
checkMemoryLeak . checkReallocUsage ( ) ;
checkMemoryLeak . check ( ) ;
2008-12-18 22:28:57 +01:00
}
2009-08-23 11:26:17 +02:00
2008-12-18 22:28:57 +01:00
void run ( )
{
2009-08-23 11:26:17 +02:00
// Check that getcode works correctly..
TEST_CASE ( testgetcode ) ;
2010-01-18 21:34:11 +01:00
// check that call_func works correctly..
TEST_CASE ( call_func ) ;
2009-08-25 22:18:22 +02:00
// Check that simplifycode works correctly..
TEST_CASE ( simplifycode ) ;
2009-08-23 15:48:25 +02:00
// Check that errors are found..
TEST_CASE ( findleak ) ;
2009-08-23 11:26:17 +02:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( simple5 ) ;
TEST_CASE ( simple7 ) ;
TEST_CASE ( simple9 ) ; // Bug 2435468 - member function "free"
2009-06-17 21:42:49 +02:00
TEST_CASE ( simple11 ) ;
2009-06-05 06:03:48 +02:00
TEST_CASE ( new_nothrow ) ;
2009-01-05 16:49:57 +01:00
2009-07-06 12:20:13 +02:00
TEST_CASE ( staticvar ) ;
2009-10-04 14:24:41 +02:00
TEST_CASE ( externvar ) ;
2009-07-06 12:20:13 +02:00
2009-02-07 10:44:57 +01:00
TEST_CASE ( alloc_alloc_1 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( ifelse6 ) ;
TEST_CASE ( ifelse7 ) ;
TEST_CASE ( ifelse8 ) ;
2009-02-25 20:20:23 +01:00
TEST_CASE ( ifelse10 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( if4 ) ;
TEST_CASE ( if7 ) ; // Bug 2401436
TEST_CASE ( if8 ) ; // Bug 2458532
2009-03-25 18:31:40 +01:00
TEST_CASE ( if9 ) ; // if (realloc)
2009-03-28 20:50:09 +01:00
TEST_CASE ( if10 ) ; // else if (realloc)
2009-02-04 07:11:36 +01:00
TEST_CASE ( if11 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( forwhile5 ) ;
TEST_CASE ( forwhile6 ) ;
2009-03-28 20:50:09 +01:00
TEST_CASE ( forwhile8 ) ; // Bug 2429936
2009-04-05 01:55:45 +02:00
TEST_CASE ( forwhile9 ) ;
TEST_CASE ( forwhile10 ) ;
2009-06-20 13:58:30 +02:00
TEST_CASE ( forwhile11 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( switch2 ) ;
2009-01-17 08:55:40 +01:00
TEST_CASE ( switch3 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( ret5 ) ; // Bug 2458436 - return use
2009-02-24 07:23:21 +01:00
TEST_CASE ( ret6 ) ;
2009-03-03 21:39:17 +01:00
TEST_CASE ( ret7 ) ;
2009-06-05 08:56:46 +02:00
TEST_CASE ( ret8 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( mismatch1 ) ;
2009-02-06 07:11:47 +01:00
TEST_CASE ( mismatch2 ) ;
TEST_CASE ( mismatch3 ) ;
2009-02-02 06:58:50 +01:00
TEST_CASE ( mismatch4 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( func3 ) ;
TEST_CASE ( func4 ) ;
TEST_CASE ( func5 ) ;
TEST_CASE ( func6 ) ;
2009-03-25 18:31:40 +01:00
TEST_CASE ( func7 ) ;
2009-01-05 16:49:57 +01:00
TEST_CASE ( func9 ) ; // Embedding the function call in a if-condition
TEST_CASE ( func10 ) ; // Bug 2458510 - Function pointer
TEST_CASE ( func11 ) ; // Bug 2458510 - Function pointer
TEST_CASE ( func12 ) ;
2009-01-24 19:55:56 +01:00
TEST_CASE ( func13 ) ;
2009-06-12 17:31:29 +02:00
TEST_CASE ( func14 ) ;
2009-06-16 19:05:05 +02:00
TEST_CASE ( func15 ) ;
2009-08-18 20:49:08 +02:00
TEST_CASE ( func16 ) ;
2010-02-06 22:35:36 +01:00
TEST_CASE ( func17 ) ;
2010-05-30 20:30:08 +02:00
TEST_CASE ( func18 ) ;
2010-09-19 12:16:29 +02:00
TEST_CASE ( func19 ) ; // Ticket #2056 - if (!f(p)) return 0;
2010-11-10 18:24:40 +01:00
TEST_CASE ( func20 ) ; // Ticket #2182 - exit is not handled
2009-01-05 16:49:57 +01:00
2009-06-15 17:44:59 +02:00
TEST_CASE ( allocfunc1 ) ;
2009-08-05 21:18:16 +02:00
TEST_CASE ( allocfunc2 ) ;
2010-04-24 20:40:57 +02:00
TEST_CASE ( allocfunc3 ) ;
2010-05-09 13:46:13 +02:00
TEST_CASE ( allocfunc4 ) ;
2010-06-05 01:58:50 +02:00
TEST_CASE ( allocfunc5 ) ;
2010-06-30 09:21:15 +02:00
TEST_CASE ( allocfunc6 ) ;
2009-06-15 17:44:59 +02:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( throw1 ) ;
TEST_CASE ( throw2 ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( linux_list_1 ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( sizeof1 ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( realloc1 ) ;
2009-03-28 20:50:09 +01:00
TEST_CASE ( realloc2 ) ;
2009-03-23 18:34:59 +01:00
TEST_CASE ( realloc3 ) ;
2009-03-28 20:50:09 +01:00
TEST_CASE ( realloc4 ) ;
2009-08-02 21:23:47 +02:00
TEST_CASE ( realloc5 ) ;
2009-08-10 22:04:28 +02:00
TEST_CASE ( realloc6 ) ;
2010-07-19 08:55:39 +02:00
TEST_CASE ( realloc7 ) ;
2010-07-27 08:17:27 +02:00
TEST_CASE ( realloc8 ) ;
2010-08-24 20:58:22 +02:00
TEST_CASE ( realloc9 ) ;
2010-09-11 11:15:04 +02:00
TEST_CASE ( realloc10 ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( assign ) ;
2008-12-18 22:28:57 +01:00
2009-03-25 18:31:40 +01:00
TEST_CASE ( varid ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( cast1 ) ;
2008-12-18 22:28:57 +01:00
2009-07-21 13:04:13 +02:00
// Using deallocated memory:
// * It is ok to take the address to deallocated memory
// * It is not ok to dereference a pointer to deallocated memory
TEST_CASE ( dealloc_use ) ;
2009-01-15 21:34:39 +01:00
// free a free'd pointer
2009-01-16 17:29:41 +01:00
TEST_CASE ( freefree1 ) ;
TEST_CASE ( freefree2 ) ;
2009-06-06 20:55:16 +02:00
TEST_CASE ( strcpy_result_assignment ) ;
2009-01-25 21:57:34 +01:00
TEST_CASE ( strcat_result_assignment ) ;
2009-01-31 14:57:27 +01:00
TEST_CASE ( all1 ) ; // Extra checking when --all is given
2009-02-07 11:54:39 +01:00
TEST_CASE ( malloc_constant_1 ) ; // Check that the malloc constant matches the type
2009-02-08 09:21:15 +01:00
// Calls to unknown functions.. they may throw exception, quit the program, etc
2009-02-08 12:59:04 +01:00
TEST_CASE ( unknownFunction1 ) ;
2009-02-08 19:27:09 +01:00
TEST_CASE ( unknownFunction2 ) ;
2009-06-21 13:48:39 +02:00
TEST_CASE ( unknownFunction4 ) ;
2009-06-23 18:29:43 +02:00
TEST_CASE ( unknownFunction5 ) ;
2009-02-20 07:28:18 +01:00
2009-12-30 21:29:54 +01:00
// detect leak in class member function..
TEST_CASE ( class1 ) ;
2009-04-28 20:01:35 +02:00
TEST_CASE ( autoptr1 ) ;
2009-05-01 11:28:33 +02:00
TEST_CASE ( if_with_and ) ;
2009-05-06 20:20:25 +02:00
TEST_CASE ( assign_pclose ) ;
2009-05-10 08:01:38 +02:00
// Using the function "exit"
TEST_CASE ( exit2 ) ;
2009-07-23 16:30:30 +02:00
TEST_CASE ( exit4 ) ;
2009-08-04 21:34:14 +02:00
TEST_CASE ( exit5 ) ;
2009-11-14 09:06:28 +01:00
TEST_CASE ( noreturn ) ;
2009-05-12 21:04:49 +02:00
TEST_CASE ( stdstring ) ;
2009-05-19 22:29:10 +02:00
TEST_CASE ( strndup_function ) ;
2009-06-01 12:40:24 +02:00
TEST_CASE ( tmpfile_function ) ;
2009-05-22 16:47:40 +02:00
TEST_CASE ( fcloseall_function ) ;
2009-05-23 13:01:18 +02:00
TEST_CASE ( file_functions ) ;
2009-07-18 13:32:55 +02:00
TEST_CASE ( getc_function ) ;
2009-05-22 09:24:03 +02:00
2009-06-21 17:01:43 +02:00
TEST_CASE ( open_function ) ;
TEST_CASE ( creat_function ) ;
TEST_CASE ( close_function ) ;
TEST_CASE ( fd_functions ) ;
2009-05-22 09:24:03 +02:00
TEST_CASE ( opendir_function ) ;
TEST_CASE ( fdopendir_function ) ;
TEST_CASE ( closedir_function ) ;
TEST_CASE ( dir_functions ) ;
2009-05-22 22:36:03 +02:00
TEST_CASE ( pointer_to_pointer ) ;
2009-05-27 21:16:54 +02:00
TEST_CASE ( dealloc_and_alloc_in_func ) ;
2009-07-31 23:42:21 +02:00
// Unknown syntax
TEST_CASE ( unknownSyntax1 ) ;
2009-10-01 10:56:59 +02:00
TEST_CASE ( knownFunctions ) ;
2009-10-12 21:36:28 +02:00
TEST_CASE ( same_function_name ) ;
2010-04-24 22:24:03 +02:00
// #1440 - Check function parameters also..
TEST_CASE ( functionParameter ) ;
2010-09-03 07:18:01 +02:00
// setjmp/longjmp..
TEST_CASE ( jmp ) ;
2010-09-27 12:25:34 +02:00
TEST_CASE ( trac1949 ) ;
2008-12-18 22:28:57 +01:00
}
2010-09-08 20:03:22 +02:00
std : : string getcode ( const char code [ ] , const char varname [ ] , bool classfunc = false ) const
2008-12-18 22:28:57 +01:00
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2009-08-23 11:26:17 +02:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , NULL ) ;
2009-08-23 11:26:17 +02:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
2009-09-30 22:27:00 +02:00
tokenizer . simplifyTokenList ( ) ;
2009-06-14 19:32:34 +02:00
2010-04-09 21:40:37 +02:00
const unsigned int varId ( Token : : findmatch ( tokenizer . tokens ( ) , varname ) - > varId ( ) ) ;
2008-12-18 22:28:57 +01:00
2009-08-23 11:26:17 +02:00
// getcode..
2010-12-01 18:00:55 +01:00
CheckMemoryLeakInFunction checkMemoryLeak ( & tokenizer , & settings , NULL ) ;
2009-11-15 09:53:38 +01:00
checkMemoryLeak . parse_noreturn ( ) ;
2009-08-23 11:26:17 +02:00
std : : list < const Token * > callstack ;
2009-10-03 21:46:22 +02:00
callstack . push_back ( 0 ) ;
2009-08-23 11:26:17 +02:00
CheckMemoryLeak : : AllocType allocType , deallocType ;
allocType = deallocType = CheckMemoryLeak : : No ;
2010-09-08 20:03:22 +02:00
Token * tokens = checkMemoryLeak . getcode ( tokenizer . tokens ( ) , callstack , varId , allocType , deallocType , classfunc , 1 ) ;
2009-08-23 11:26:17 +02:00
// stringify..
std : : ostringstream ret ;
2010-04-02 07:30:58 +02:00
for ( const Token * tok = tokens ; tok ; tok = tok - > next ( ) )
2009-08-23 11:26:17 +02:00
ret < < tok - > str ( ) ;
Tokenizer : : deleteTokens ( tokens ) ;
return ret . str ( ) ;
2008-12-18 22:28:57 +01:00
}
2009-08-30 21:11:15 +02:00
2009-08-23 11:26:17 +02:00
void testgetcode ( )
2008-12-18 22:28:57 +01:00
{
2009-08-23 11:26:17 +02:00
// alloc;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int *a = malloc(100); " , " a " ) ) ;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int *a = new int; " , " a " ) ) ;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int *a = new int[10]; " , " a " ) ) ;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int * const a = new int[10]; " , " a " ) ) ;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " const int * const a = new int[10]; " , " a " ) ) ;
2010-06-06 11:22:59 +02:00
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " char *a = g_strdup_printf( \" %i \" , f()); " , " a " ) ) ;
2008-12-18 22:28:57 +01:00
2009-08-23 11:26:17 +02:00
// alloc; return use;
ASSERT_EQUALS ( " ;;alloc;returnuse; " , getcode ( " int *a = new int[10]; return a; " , " a " ) ) ;
2009-08-29 06:42:24 +02:00
ASSERT_EQUALS ( " ;;alloc;returnuse; " , getcode ( " char *a = new char[100]; return (char *)a; " , " a " ) ) ;
2009-08-23 11:26:17 +02:00
// alloc; return;
ASSERT_EQUALS ( " ;;alloc;return; " , getcode ( " char *s = new char[100]; return 0; " , " s " ) ) ;
2010-08-04 20:48:20 +02:00
ASSERT_EQUALS ( " ;;alloc;return; " , getcode ( " char *s = new char[100]; return s[0]; " , " s " ) ) ;
2010-08-05 21:23:32 +02:00
ASSERT_EQUALS ( " ;;alloc;return; " , getcode ( " char *s = new char[100]; return strcmp(s,x); " , " s " ) ) ;
2009-08-23 11:26:17 +02:00
2009-10-03 21:46:22 +02:00
// lock/unlock..
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int a; __cppcheck_lock(); " , " " ) ) ;
ASSERT_EQUALS ( " ;;callfunc; " , getcode ( " int a; __cppcheck_lock(); " , " a " ) ) ;
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " int a; __cppcheck_unlock(); " , " " ) ) ;
ASSERT_EQUALS ( " ;;callfunc; " , getcode ( " int a; __cppcheck_unlock(); " , " a " ) ) ;
2009-08-23 11:26:17 +02:00
// dealloc;
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; free(s); " , " s " ) ) ;
2009-09-30 22:27:00 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; free((void *)s); " , " s " ) ) ;
2010-10-20 20:38:37 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; free((void *)(s)); " , " s " ) ) ;
2009-09-30 22:27:00 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; free(reinterpret_cast<void *>(s)); " , " s " ) ) ;
2009-08-23 11:26:17 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; delete s; " , " s " ) ) ;
2009-08-30 21:11:15 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; delete (s); " , " s " ) ) ;
TODO_ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; delete (void *)(s); " , " s " ) ) ;
2009-08-23 11:26:17 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; delete [] s; " , " s " ) ) ;
2009-08-30 21:11:15 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; delete [] (s); " , " s " ) ) ;
2009-10-04 13:10:08 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " void *p; foo(fclose(p)); " , " p " ) ) ;
2009-11-18 17:17:37 +01:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " void *p; foo(close(p)); " , " p " ) ) ;
2010-05-29 21:56:18 +02:00
ASSERT_EQUALS ( " ;;;; " , getcode ( " FILE *f1; FILE *f2; fclose(f1); " , " f2 " ) ) ;
2010-11-11 17:40:20 +01:00
ASSERT_EQUALS ( " ;;returnuse; " , getcode ( " FILE *f; return fclose(f) == EOF ? 1 : 2; " , " f " ) ) ;
2009-08-23 11:26:17 +02:00
// if..
ASSERT_EQUALS ( " ;;if{} " , getcode ( " char *s; if (a) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;dealloc;ifv{} " , getcode ( " FILE *f; if (fclose(f)) { } " , " f " ) ) ;
ASSERT_EQUALS ( " ;;if(!var){}else{} " , getcode ( " char *s; if (!s) { } else { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;if{} " , getcode ( " char *s; if (a && s) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;if(!var){} " , getcode ( " char *s; if (a && !s) { } " , " s " ) ) ;
2010-03-13 17:11:48 +01:00
ASSERT_EQUALS ( " ;;ifv{} " , getcode ( " char *s; if (foo(!s)) { } " , " s " ) ) ;
2009-09-24 22:40:18 +02:00
ASSERT_EQUALS ( " ;;;if{dealloc;};if{dealloc;return;}assign;returnuse; " , getcode ( " char *buf, *tmp; tmp = realloc(buf, 40); if (!(tmp)) { free(buf); return; } buf = tmp; return buf; " , " buf " ) ) ;
2010-05-31 18:20:34 +02:00
ASSERT_EQUALS ( " ;;if{} " , getcode ( " FILE *f; if (fgets(buf,100,f)){} " , " f " ) ) ;
2010-11-30 19:14:09 +01:00
ASSERT_EQUALS ( " ;;alloc;if(var){dealloc;} " , getcode ( " int fd = open(a,b); if (0 < fd) { close(fd); } " , " fd " ) ) ;
2009-09-04 19:11:19 +02:00
2009-08-25 22:18:22 +02:00
// switch..
2009-09-30 22:27:00 +02:00
ASSERT_EQUALS ( " ;;switch{case;;break;}; " , getcode ( " char *s; switch(a){case 1: break;}; " , " s " ) ) ;
2009-08-25 22:18:22 +02:00
2009-08-23 11:26:17 +02:00
// loop..
ASSERT_EQUALS ( " ;;loop{} " , getcode ( " char *s; while (a) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;loopcallfunc{} " , getcode ( " char *s; while (a()) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;loop{} " , getcode ( " char *s; for (a;b;c) { } " , " s " ) ) ;
2009-08-25 22:18:22 +02:00
ASSERT_EQUALS ( " ;;loop{alloc;} " , getcode ( " char *s; for (a;b;c) { s=malloc(10); } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;do{}loop; " , getcode ( " char *s; do { } while (a); " , " s " ) ) ;
2009-09-27 21:49:07 +02:00
ASSERT_EQUALS ( " ;;while1{} " , getcode ( " char *s; while(true) { } " , " s " ) ) ;
2009-10-04 19:58:41 +02:00
ASSERT_EQUALS ( " ;;while1{} " , getcode ( " char *s; for(;;) { } " , " s " ) ) ;
2010-01-24 21:48:39 +01:00
ASSERT_EQUALS ( " ;;while(var){} " , getcode ( " char *s; while (s) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;while(!var){} " , getcode ( " char *s; while (!s) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;alloc;while(var){} " , getcode ( " int fd = open(); while (fd >= 0) { } " , " fd " ) ) ;
ASSERT_EQUALS ( " ;;alloc;while(!var){} " , getcode ( " int fd = open(); while (fd < 0) { } " , " fd " ) ) ;
2009-08-23 11:26:17 +02:00
2009-08-28 23:26:40 +02:00
// asprintf..
2009-08-29 07:02:36 +02:00
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " char *s; asprintf(&s, \" xyz \" ); " , " s " ) ) ;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " char *s; asprintf(&s, \" s: %s \" , s); " , " s " ) ) ;
2009-08-28 23:26:40 +02:00
ASSERT_EQUALS ( " ;;; " , getcode ( " char *s; asprintf(&p, \" s: %s \" , s); " , " s " ) ) ;
2009-08-29 08:20:18 +02:00
// Since we don't check how the return value is used we must bail out
2009-08-29 07:26:32 +02:00
ASSERT_EQUALS ( " " , getcode ( " char *s; int ret = asprintf(&s, \" xyz \" ); " , " s " ) ) ;
TODO_ASSERT_EQUALS ( " ;;alloc; " , getcode ( " char *s; int ret; ret=asprintf(&s, \" xyz \" ); if (ret==-1) return; " , " s " ) ) ;
2009-08-23 11:26:17 +02:00
// use..
2009-08-30 21:11:15 +02:00
ASSERT_EQUALS ( " ;;use; " , getcode ( " char *s; a(s); " , " s " ) ) ;
ASSERT_EQUALS ( " ;;use; " , getcode ( " char *s; (*a)(s); " , " s " ) ) ;
ASSERT_EQUALS ( " ;;use; " , getcode ( " char *s; abc.a(s); " , " s " ) ) ;
2009-08-23 11:26:17 +02:00
ASSERT_EQUALS ( " ;;use; " , getcode ( " char *s; s2 = s; " , " s " ) ) ;
ASSERT_EQUALS ( " ;;use; " , getcode ( " char *s; s2 = s + 10; " , " s " ) ) ;
2010-02-06 21:47:52 +01:00
ASSERT_EQUALS ( " ;;use; " , getcode ( " char *s; s2 = x + s; " , " s " ) ) ;
2010-05-24 19:28:27 +02:00
ASSERT_EQUALS ( " ;;use;if{;} " , getcode ( " char *s; if (foo(s)) ; " , " s " ) ) ;
2010-06-21 18:43:28 +02:00
ASSERT_EQUALS ( " ;;use; " , getcode ( " char *s; map1[s] = 0; " , " s " ) ) ;
2010-11-29 19:53:34 +01:00
ASSERT_EQUALS ( " ;;;use; " , getcode ( " char *p; const char *q; q = p; " , " p " ) ) ;
2010-10-20 18:39:40 +02:00
ASSERT_EQUALS ( " ;;use;; " , getcode ( " char *s; x = {1,s}; " , " s " ) ) ;
2010-11-29 19:53:34 +01:00
ASSERT_EQUALS ( " ;{};;alloc;;use; " , getcode ( " struct Foo { }; Foo *p; p = malloc(10); const Foo *q; q = p; " , " p " ) ) ;
2010-11-30 19:36:04 +01:00
ASSERT_EQUALS ( " ;;alloc;use; " , getcode ( " Fred *fred; p.setFred(fred = new Fred); " , " fred " ) ) ;
2009-08-23 11:26:17 +02:00
2010-11-20 08:35:23 +01:00
// non-use..
ASSERT_EQUALS ( " ;; " , getcode ( " char *s; s = s + 1; " , " s " ) ) ;
2009-08-30 21:11:15 +02:00
// return..
ASSERT_EQUALS ( " ;;return; " , getcode ( " char *s; return; " , " s " ) ) ;
ASSERT_EQUALS ( " ;;returnuse; " , getcode ( " char *s; return s; " , " s " ) ) ;
2010-08-04 23:01:32 +02:00
ASSERT_EQUALS ( " ;;return; " , getcode ( " char *s; return 5 + s[0]; " , " s " ) ) ;
2009-08-30 21:11:15 +02:00
2009-08-23 11:26:17 +02:00
// assign..
ASSERT_EQUALS ( " ;;assign; " , getcode ( " char *s; s = 0; " , " s " ) ) ;
2009-08-29 17:33:57 +02:00
ASSERT_EQUALS ( " ;;; " , getcode ( " char *s; s = strcpy(s, p); " , " s " ) ) ;
2009-08-23 11:26:17 +02:00
// callfunc..
2009-08-30 21:11:15 +02:00
ASSERT_EQUALS ( " ;;assigncallfunc; " , getcode ( " char *s; s = a(); " , " s " ) ) ;
2009-08-23 11:26:17 +02:00
ASSERT_EQUALS ( " ;;callfunc; " , getcode ( " char *s; a(); " , " s " ) ) ;
2009-08-30 21:11:15 +02:00
ASSERT_EQUALS ( " ;;callfunc; " , getcode ( " char *s; abc.a(); " , " s " ) ) ;
2009-08-23 11:26:17 +02:00
// exit..
ASSERT_EQUALS ( " ;;exit; " , getcode ( " char *s; exit(0); " , " s " ) ) ;
2009-09-12 14:11:17 +02:00
ASSERT_EQUALS ( " ;;exit; " , getcode ( " char *s; _exit(0); " , " s " ) ) ;
ASSERT_EQUALS ( " ;;exit; " , getcode ( " char *s; abort(); " , " s " ) ) ;
ASSERT_EQUALS ( " ;;exit; " , getcode ( " char *s; err(0); " , " s " ) ) ;
2009-08-25 22:18:22 +02:00
ASSERT_EQUALS ( " ;;if{exit;} " , getcode ( " char *s; if (a) { exit(0); } " , " s " ) ) ;
2009-08-29 07:43:44 +02:00
2009-11-15 10:30:00 +01:00
// list_for_each
ASSERT_EQUALS ( " ;;exit;{} " , getcode ( " char *s; list_for_each(x,y,z) { } " , " s " ) ) ;
2009-08-29 07:43:44 +02:00
// open/close
2009-09-30 20:42:14 +02:00
ASSERT_EQUALS ( " ;;alloc;if(var){dealloc;} " , getcode ( " int f; f=open(); if(f>=0)close(f); " , " f " ) ) ;
ASSERT_EQUALS ( " ;;alloc;ifv{;} " , getcode ( " int f; f=open(); if(f!=-1 || x); " , " f " ) ) ;
2010-05-29 21:11:59 +02:00
ASSERT_EQUALS ( " ;;;dealloc;loop{}} " , getcode ( " ;int f; while (close(f) == -1) { } } " , " f " ) ) ;
2009-12-22 19:13:46 +01:00
2009-12-22 19:18:02 +01:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " int f; e |= fclose(f); " , " f " ) ) ;
2010-01-07 21:36:51 +01:00
// fcloseall..
ASSERT_EQUALS ( " ;;alloc;; " , getcode ( " char *s; s = malloc(10); fcloseall(); " , " s " ) ) ;
ASSERT_EQUALS ( " ;;alloc;dealloc; " , getcode ( " FILE *f; f = fopen(a,b); fcloseall(); " , " f " ) ) ;
2010-09-08 20:03:22 +02:00
// call memcpy in class function..
ASSERT_EQUALS ( " ;;alloc;; " , getcode ( " char *s; s = new char[10]; memcpy(s,a); " , " s " , true ) ) ;
2010-10-21 19:42:09 +02:00
// #2112 - Segmentation fault in the getcode function
getcode ( " page *one = foo(); \n "
" ASSERT(one, return 0) \n "
" const int two = rand(); \n "
" return 0; \n "
" } " , " one " ) ;
2009-08-25 22:18:22 +02:00
}
2010-01-18 21:34:11 +01:00
void call_func ( )
{
// whitelist..
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " qsort " ) ) ;
2010-01-18 21:58:27 +01:00
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " scanf " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " sscanf " ) ) ;
2010-01-18 21:34:11 +01:00
2010-01-20 22:03:06 +01:00
// #1293
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " time " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " asctime " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " asctime_r " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " ctime " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " ctime_r " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " gmtime " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " gmtime_r " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " localtime " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " localtime_r " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " memcmp " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " gets " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " vprintf " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " vfprintf " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " vsprintf " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " snprintf " ) ) ;
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( " vsnprintf " ) ) ;
2010-01-18 21:34:11 +01:00
static const char * const call_func_white_list [ ] =
{
" asprintf " , " atof " , " atoi " , " atol " , " clearerr " , " delete " , " fchmod " , " fcntl "
, " fdatasync " , " feof " , " ferror " , " fflush " , " fgetc " , " fgetpos " , " fgets "
, " flock " , " for " , " fprintf " , " fputc " , " fputs " , " fread " , " free " , " fscanf " , " fseek "
, " fseeko " , " fsetpos " , " fstat " , " fsync " , " ftell " , " ftello " , " ftruncate "
, " fwrite " , " getc " , " if " , " ioctl " , " lockf " , " lseek " , " memchr " , " memcpy "
, " memmove " , " memset " , " posix_fadvise " , " posix_fallocate " , " pread "
, " printf " , " puts " , " pwrite " , " read " , " readahead " , " readdir " , " readdir_r " , " readv "
, " realloc " , " return " , " rewind " , " rewinddir " , " scandir " , " seekdir "
, " setbuf " , " setbuffer " , " setlinebuf " , " setvbuf " , " snprintf " , " sprintf " , " strcasecmp "
, " strcat " , " strchr " , " strcmp " , " strcpy " , " stricmp " , " strlen " , " strncat " , " strncmp "
, " strncpy " , " strrchr " , " strstr " , " strtod " , " strtol " , " strtoul " , " switch "
, " sync_file_range " , " telldir " , " typeid " , " while " , " write " , " writev "
} ;
2010-04-02 07:30:58 +02:00
for ( unsigned int i = 0 ; i < ( sizeof ( call_func_white_list ) / sizeof ( char * ) ) ; + + i )
2010-01-18 21:34:11 +01:00
ASSERT_EQUALS ( true , CheckMemoryLeakInFunction : : test_white_list ( call_func_white_list [ i ] ) ) ;
}
2009-08-25 22:18:22 +02:00
2010-05-16 19:55:16 +02:00
std : : string simplifycode ( const char code [ ] ) const
2009-08-25 22:18:22 +02:00
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2009-08-25 22:18:22 +02:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , NULL ) ;
2009-08-25 22:18:22 +02:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
2010-03-17 21:58:53 +01:00
Token * tokens = const_cast < Token * > ( tokenizer . tokens ( ) ) ;
2009-08-25 22:18:22 +02:00
// replace "if ( ! var )" => "if(!var)"
2010-04-02 07:30:58 +02:00
for ( Token * tok = tokens ; tok ; tok = tok - > next ( ) )
2009-08-25 22:18:22 +02:00
{
2010-04-02 07:30:58 +02:00
if ( Token : : Match ( tok , " if|while ( var ) " ) )
2009-08-25 22:18:22 +02:00
{
Token : : eraseTokens ( tok , tok - > tokAt ( 4 ) ) ;
2010-01-24 21:48:39 +01:00
tok - > str ( tok - > str ( ) + " (var) " ) ;
2009-08-25 22:18:22 +02:00
}
2010-04-02 07:30:58 +02:00
else if ( Token : : Match ( tok , " if|while ( ! var ) " ) )
2009-08-25 22:18:22 +02:00
{
Token : : eraseTokens ( tok , tok - > tokAt ( 5 ) ) ;
2010-01-24 21:48:39 +01:00
tok - > str ( tok - > str ( ) + " (!var) " ) ;
2010-01-19 19:08:03 +01:00
}
2009-08-25 22:18:22 +02:00
}
CheckMemoryLeakInFunction checkMemoryLeak ( & tokenizer , & settings , NULL ) ;
2010-05-16 19:55:16 +02:00
checkMemoryLeak . simplifycode ( tokens ) ;
2009-08-25 22:18:22 +02:00
std : : ostringstream ret ;
2010-04-02 07:30:58 +02:00
for ( const Token * tok = tokenizer . tokens ( ) ; tok ; tok = tok - > next ( ) )
2009-08-25 22:18:22 +02:00
ret < < ( tok - > previous ( ) ? " " : " " ) < < tok - > str ( ) ;
return ret . str ( ) ;
2008-12-18 22:28:57 +01:00
}
2009-08-25 22:18:22 +02:00
// Test that the CheckMemoryLeaksInFunction::simplifycode works
void simplifycode ( )
{
ASSERT_EQUALS ( " ; " , simplifycode ( " ; ; ; ; " ) ) ;
ASSERT_EQUALS ( " ; " , simplifycode ( " ; if ; " ) ) ;
ASSERT_EQUALS ( " alloc ; " , simplifycode ( " alloc ; if ; if(var) ; ifv ; if(!var) ; " ) ) ;
ASSERT_EQUALS ( " alloc ; " , simplifycode ( " alloc ; if ; else ; " ) ) ;
2010-09-11 20:18:16 +02:00
// use..
2010-09-11 21:32:21 +02:00
ASSERT_EQUALS ( " ; use ; } " , simplifycode ( " ; use use ; } " ) ) ;
2010-09-11 20:18:16 +02:00
ASSERT_EQUALS ( " ; alloc ; dealloc ; } " , simplifycode ( " ; alloc ; use ; use ; if use ; dealloc ; } " ) ) ;
2009-08-25 22:18:22 +02:00
// if, else..
ASSERT_EQUALS ( " ; alloc ; if break ; dealloc ; " , simplifycode ( " ; alloc ; if { break; } dealloc ; " ) ) ;
ASSERT_EQUALS ( " ; alloc ; if continue ; dealloc ; " , simplifycode ( " ; alloc ; if { continue; } dealloc ; " ) ) ;
ASSERT_EQUALS ( " ; alloc ; " , simplifycode ( " ; alloc; if { return use; } " ) ) ;
ASSERT_EQUALS ( " ; alloc ; dealloc ; " , simplifycode ( " ; alloc; if(!var) { return; } dealloc; " ) ) ;
ASSERT_EQUALS ( " ; alloc ; " , simplifycode ( " ; if { alloc; } else { return; } " ) ) ;
ASSERT_EQUALS ( " ; alloc ; dealloc ; " , simplifycode ( " ; alloc ; if(!var) { alloc ; } dealloc ; " ) ) ;
2009-08-30 21:11:15 +02:00
ASSERT_EQUALS ( " ; use ; " , simplifycode ( " ; if(var) use ; " ) ) ;
2010-11-27 11:09:42 +01:00
ASSERT_EQUALS ( " ; " , simplifycode ( " ; if break ; else break ; " ) ) ;
2010-01-12 19:12:08 +01:00
ASSERT_EQUALS ( " ; alloc ; if return ; " , simplifycode ( " ; alloc ; loop { if return ; if continue ; } " ) ) ;
2010-11-27 11:09:42 +01:00
ASSERT_EQUALS ( " ; alloc ; loop return ; " , simplifycode ( " ; alloc ; loop { if continue ; else return ; } " ) ) ;
2009-08-30 21:11:15 +02:00
2010-05-16 19:55:16 +02:00
ASSERT_EQUALS ( " ; alloc ; if dealloc ; " , simplifycode ( " ; alloc ; if(!var) { return ; } if { dealloc ; } " ) ) ;
2009-09-23 22:42:07 +02:00
ASSERT_EQUALS ( " ; if alloc ; else assign ; return use ; " , simplifycode ( " ; callfunc ; if callfunc { alloc ; } else { assign ; } return use ; " ) ) ;
2010-01-14 21:41:50 +01:00
ASSERT_EQUALS ( " ; dealloc ; return ; " , simplifycode ( " ; while1 { if callfunc { dealloc ; return ; } else { continue ; } } " ) ) ;
2009-12-13 19:50:49 +01:00
2009-08-29 16:27:16 +02:00
// "if ; .."
ASSERT_EQUALS ( " ; if xxx ; " , simplifycode ( " ; if ; else xxx ; " ) ) ;
ASSERT_EQUALS ( " ; if(var) xxx ; " , simplifycode ( " ; if(!var) ; else xxx ; " ) ) ;
ASSERT_EQUALS ( " ; if(!var) xxx ; " , simplifycode ( " ; if(var) ; else xxx ; " ) ) ;
ASSERT_EQUALS ( " ; ifv xxx ; " , simplifycode ( " ; ifv ; else xxx ; " ) ) ;
2009-09-01 20:02:28 +02:00
ASSERT_EQUALS ( " ; alloc ; " , simplifycode ( " ; alloc; if { dealloc; return; } " ) ) ;
2009-10-01 22:25:59 +02:00
ASSERT_EQUALS ( " ; alloc ; " , simplifycode ( " ; alloc; if { return use; } " ) ) ;
2009-09-01 20:12:53 +02:00
ASSERT_EQUALS ( " ; alloc ; return ; " , simplifycode ( " ;alloc;if{return;}return; " ) ) ;
2010-05-16 19:55:16 +02:00
ASSERT_EQUALS ( " ; alloc ; if assign ; dealloc ; " , simplifycode ( " ;alloc;if{assign;}dealloc; " ) ) ;
2009-08-25 22:18:22 +02:00
2010-02-20 10:17:45 +01:00
// if(var)
ASSERT_EQUALS ( " ; alloc ; return use ; " , simplifycode ( " ; alloc ; return use ; " ) ) ;
2010-03-13 17:11:48 +01:00
ASSERT_EQUALS ( " ; alloc ; return use ; " , simplifycode ( " ; alloc ; ifv return ; return use ; " ) ) ;
2010-02-20 10:17:45 +01:00
2009-08-25 22:18:22 +02:00
// switch..
ASSERT_EQUALS ( " ; alloc ; dealloc ; " , simplifycode ( " ;alloc;switch{case;break;};dealloc; " ) ) ;
2010-09-12 21:41:13 +02:00
ASSERT_EQUALS ( " ; " , simplifycode ( " ; switch { case ; return ; default ; break ; } " ) ) ;
ASSERT_EQUALS ( " ; " , simplifycode ( " ; switch { case ; if { return ; } break ; default ; break ; } " ) ) ;
ASSERT_EQUALS ( " ; use ; " , simplifycode ( " ; switch { case ; return ; default ; use ; break ; } " ) ) ;
2010-01-10 20:03:46 +01:00
ASSERT_EQUALS ( " ; use ; " , simplifycode ( " ; while1 { loop { ; } switch { case ; dealloc ; return ; default ; break ; } } " ) ) ;
2010-05-29 20:55:09 +02:00
ASSERT_EQUALS ( " ; { dealloc ; return ; } } " , simplifycode ( " switch { case ; case ; dealloc ; return ; default ; dealloc ; return ; } } " ) ) ;
2009-08-25 22:18:22 +02:00
// loops..
2010-01-10 15:40:50 +01:00
ASSERT_EQUALS ( " ; " , simplifycode ( " ; loop { ; } " ) ) ;
2009-09-26 07:19:22 +02:00
ASSERT_EQUALS ( " ; " , simplifycode ( " ; loop { break; } " ) ) ;
2009-08-25 22:18:22 +02:00
ASSERT_EQUALS ( " ; " , simplifycode ( " ; loop { if { break; } } " ) ) ;
ASSERT_EQUALS ( " ; loop alloc ; " , simplifycode ( " ; loop { alloc ; } " ) ) ;
ASSERT_EQUALS ( " ; alloc ; alloc ; " , simplifycode ( " ; alloc ; do { alloc ; } loop ; " ) ) ;
2009-09-15 22:26:38 +02:00
ASSERT_EQUALS ( " ; exit ; " , simplifycode ( " ; alloc ; do { } loop ; exit ; " ) ) ;
2010-09-11 21:07:35 +02:00
ASSERT_EQUALS ( " ; loop use ; " , simplifycode ( " ; loop { loop loop use ; } ; " ) ) ;
2010-09-11 21:48:40 +02:00
ASSERT_EQUALS ( " ; } " , simplifycode ( " ; loop { if break ; break ; } ; } " ) ) ;
2010-09-12 21:15:19 +02:00
ASSERT_EQUALS ( " ; } " , simplifycode ( " ; loop { if continue ; if continue ; } ; } " ) ) ;
2009-08-25 22:18:22 +02:00
2010-01-24 21:48:39 +01:00
ASSERT_EQUALS ( " ; alloc ; " , simplifycode ( " ; alloc ; while(!var) alloc ; " ) ) ;
2010-01-19 19:08:03 +01:00
2010-01-14 21:41:50 +01:00
ASSERT_EQUALS ( " ; alloc ; dealloc ; return ; " , simplifycode ( " ; alloc ; while1 { if { dealloc ; return ; } } " ) ) ;
ASSERT_EQUALS ( " ; alloc ; dealloc ; return ; " , simplifycode ( " ; alloc ; while1 { if { dealloc ; return ; } if { continue ; } } " ) ) ;
ASSERT_EQUALS ( " ; alloc ; " , simplifycode ( " ; alloc ; while1 { if { dealloc ; return ; } if { break ; } } " ) ) ;
2010-11-10 17:46:40 +01:00
ASSERT_EQUALS ( " ; alloc ; use ; } " , simplifycode ( " ; alloc ; while1 { if { dealloc ; return ; } continue ; } ; } " ) ) ;
2009-09-27 21:49:07 +02:00
2010-01-24 21:48:39 +01:00
ASSERT_EQUALS ( " ; " , simplifycode ( " ; do { dealloc ; alloc ; } while(var) ; " ) ) ;
2010-08-02 22:14:51 +02:00
ASSERT_EQUALS ( " dealloc ; alloc ; " , simplifycode ( " loop { dealloc ; alloc ; } " ) ) ;
ASSERT_EQUALS ( " dealloc ; alloc ; " , simplifycode ( " while1 { dealloc ; alloc ; } " ) ) ;
2010-09-12 20:45:30 +02:00
ASSERT_EQUALS ( " use ; } " , simplifycode ( " loop { use ; callfunc ; } } " ) ) ;
2010-01-24 21:48:39 +01:00
2010-11-27 11:09:42 +01:00
ASSERT_EQUALS ( " ; " , simplifycode ( " ; loop { if { continue ; } else { if continue ; } } " ) ) ;
ASSERT_EQUALS ( " ; " , simplifycode ( " ; loop { { if continue ; if continue ; } } " ) ) ;
2010-04-27 20:43:31 +02:00
// scope..
// current result - ok
ASSERT_EQUALS ( " ; assign ; dealloc ; if alloc ; } " , simplifycode ( " ; assign ; { dealloc ; if alloc ; } } " ) ) ;
// wanted result - better
TODO_ASSERT_EQUALS ( " ; assign ; if alloc ; } " , simplifycode ( " ; assign ; { dealloc ; if alloc ; } } " ) ) ;
2009-08-30 21:11:15 +02:00
// callfunc..
2010-09-11 20:49:24 +02:00
ASSERT_EQUALS ( " ; callfunc ; } " , simplifycode ( " ;callfunc;} " ) ) ;
2010-08-02 21:59:47 +02:00
ASSERT_EQUALS ( " ; " , simplifycode ( " ;callfunc;; " ) ) ;
2010-09-11 20:49:24 +02:00
ASSERT_EQUALS ( " ; callfunc ; } " , simplifycode ( " ;callfunc callfunc ; } " ) ) ;
2010-08-02 22:14:51 +02:00
ASSERT_EQUALS ( " dealloc ; alloc ; return ; } " , simplifycode ( " while1 { dealloc ; alloc ; } callfunc ; return ; } " ) ) ;
2010-09-11 20:49:24 +02:00
ASSERT_EQUALS ( " ; } " , simplifycode ( " loop callfunc ; } " ) ) ;
2009-08-30 21:11:15 +02:00
2009-08-25 22:18:22 +02:00
// exit..
2009-09-13 07:20:42 +02:00
ASSERT_EQUALS ( " ; exit ; " , simplifycode ( " ; alloc; exit; " ) ) ;
2009-09-22 18:09:29 +02:00
ASSERT_EQUALS ( " ; exit ; " , simplifycode ( " ; alloc; if { loop ; } dealloc; exit; " ) ) ;
2009-08-25 22:18:22 +02:00
ASSERT_EQUALS ( " ; " , simplifycode ( " ; if { alloc; exit; } " ) ) ;
ASSERT_EQUALS ( " ; alloc ; " , simplifycode ( " ; alloc ; if { use; exit; } " ) ) ;
2009-08-29 16:03:23 +02:00
ASSERT_EQUALS ( " ; alloc ; " , simplifycode ( " ; alloc ; if(!var) { exit; } " ) ) ;
2009-08-25 22:18:22 +02:00
TODO_ASSERT_EQUALS ( " ; " , simplifycode ( " ; alloc ; if(var) { exit; } " ) ) ;
2009-09-19 08:23:10 +02:00
TODO_ASSERT_EQUALS ( " ; \n ; alloc ; " , simplifycode ( " ; alloc ; ifv { exit; } " ) ) ;
2009-10-27 21:28:03 +01:00
2010-09-11 21:07:35 +02:00
// try-catch
ASSERT_EQUALS ( " ; } " , simplifycode ( " ; try ; catch exit ; } " ) ) ;
2009-10-27 21:28:03 +01:00
// dealloc; dealloc;
2010-05-16 19:55:16 +02:00
ASSERT_EQUALS ( " ; alloc ; if dealloc ; dealloc ; " , simplifycode ( " ; alloc ; if { dealloc ; } dealloc ; " ) ) ;
2010-09-08 19:22:03 +02:00
// use ; dealloc ;
2010-09-19 12:16:29 +02:00
ASSERT_EQUALS ( " ; alloc ; use ; if return ; dealloc ; " , simplifycode ( " ; alloc ; use ; if { return ; } dealloc ; " ) ) ;
2009-08-25 22:18:22 +02:00
}
2009-08-23 15:48:25 +02:00
// is there a leak in given code? if so, return the linenr
2010-05-16 19:55:16 +02:00
unsigned int dofindleak ( const char code [ ] ) const
2009-08-23 15:48:25 +02:00
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2009-09-01 19:24:39 +02:00
Settings settings ;
2010-08-27 20:28:00 +02:00
settings . debug = settings . debugwarnings = true ;
2010-12-01 18:00:55 +01:00
// Tokenize..
2009-09-01 19:24:39 +02:00
Tokenizer tokenizer ( & settings , NULL ) ;
2009-08-23 15:48:25 +02:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
// replace "if ( ! var )" => "if(!var)"
2010-04-02 07:30:58 +02:00
for ( Token * tok = const_cast < Token * > ( tokenizer . tokens ( ) ) ; tok ; tok = tok - > next ( ) )
2009-08-23 15:48:25 +02:00
{
2010-04-02 07:30:58 +02:00
if ( tok - > str ( ) = = " if_var " )
2009-10-27 23:08:11 +01:00
{
tok - > str ( " if(var) " ) ;
}
2010-04-02 07:30:58 +02:00
else if ( Token : : simpleMatch ( tok , " if ( var ) " ) )
2009-08-23 15:48:25 +02:00
{
Token : : eraseTokens ( tok , tok - > tokAt ( 4 ) ) ;
tok - > str ( " if(var) " ) ;
}
2010-04-02 07:30:58 +02:00
else if ( Token : : simpleMatch ( tok , " if ( ! var ) " ) )
2009-08-23 15:48:25 +02:00
{
Token : : eraseTokens ( tok , tok - > tokAt ( 5 ) ) ;
tok - > str ( " if(!var) " ) ;
}
}
2010-05-16 19:55:16 +02:00
const Token * tok = CheckMemoryLeakInFunction : : findleak ( tokenizer . tokens ( ) ) ;
2009-12-26 17:49:05 +01:00
return ( tok ? tok - > linenr ( ) : ( unsigned int ) ( - 1 ) ) ;
2009-08-23 15:48:25 +02:00
}
void findleak ( )
{
2009-12-26 17:49:05 +01:00
static const unsigned int notfound = ( unsigned int ) ( - 1 ) ;
2009-08-23 15:48:25 +02:00
ASSERT_EQUALS ( 1 , dofindleak ( " alloc; " ) ) ;
2009-09-01 19:06:34 +02:00
ASSERT_EQUALS ( 1 , dofindleak ( " ; use; { alloc; } " ) ) ;
2009-08-23 15:48:25 +02:00
ASSERT_EQUALS ( 2 , dofindleak ( " alloc; \n return; " ) ) ;
2009-12-26 17:49:05 +01:00
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; return use; " ) ) ;
2009-08-23 15:48:25 +02:00
ASSERT_EQUALS ( 2 , dofindleak ( " alloc; \n callfunc; " ) ) ;
2009-12-26 17:49:05 +01:00
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; use; " ) ) ;
ASSERT_EQUALS ( notfound , dofindleak ( " assign; alloc; dealloc; " ) ) ;
ASSERT_EQUALS ( notfound , dofindleak ( " assign; if alloc; dealloc; " ) ) ;
2009-08-23 15:48:25 +02:00
// if alloc..
ASSERT_EQUALS ( 2 , dofindleak ( " if alloc; \n return; " ) ) ;
2009-12-26 17:49:05 +01:00
ASSERT_EQUALS ( notfound , dofindleak ( " if alloc; \n return use; " ) ) ;
ASSERT_EQUALS ( notfound , dofindleak ( " if alloc; \n use; " ) ) ;
2010-09-27 17:53:10 +02:00
ASSERT_EQUALS ( notfound , dofindleak ( " if alloc; \n if assign; \n if dealloc; } " ) ) ;
2009-08-23 15:48:25 +02:00
// if..
2009-12-26 17:49:05 +01:00
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; ifv dealloc; " ) ) ;
2009-08-23 15:48:25 +02:00
ASSERT_EQUALS ( 2 , dofindleak ( " alloc; \n if return; \n dealloc; " ) ) ;
2009-11-15 10:30:00 +01:00
ASSERT_EQUALS ( 2 , dofindleak ( " alloc; \n if continue; \n dealloc; " ) ) ;
2009-10-27 23:08:11 +01:00
ASSERT_EQUALS ( 2 , dofindleak ( " alloc; \n if_var return; \n dealloc; " ) ) ;
2009-08-23 15:48:25 +02:00
ASSERT_EQUALS ( 3 , dofindleak ( " alloc; \n if \n return; \n dealloc; " ) ) ;
2009-12-26 17:49:05 +01:00
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; if { dealloc ; return; } dealloc; " ) ) ;
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; if { dealloc ; return; } dealloc; " ) ) ;
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; if { dealloc ; alloc; } dealloc; " ) ) ;
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; \n if(!var) \n { callfunc; \n return; \n } \n use; " ) ) ;
2009-08-23 15:48:25 +02:00
2009-12-26 17:49:05 +01:00
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; if { return use; } dealloc; " ) ) ;
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; if { dealloc; return; } dealloc; " ) ) ;
2009-08-25 22:18:22 +02:00
2010-05-31 18:20:34 +02:00
ASSERT_EQUALS ( 5 , dofindleak ( " { \n ; \n alloc; \n if dealloc; \n } " ) ) ;
2009-08-23 15:48:25 +02:00
// assign..
ASSERT_EQUALS ( 2 , dofindleak ( " alloc; \n assign; \n dealloc; " ) ) ;
2009-12-26 17:49:05 +01:00
ASSERT_EQUALS ( notfound , dofindleak ( " alloc; \n if(!var) assign; \n dealloc; " ) ) ;
2010-09-27 17:53:10 +02:00
ASSERT_EQUALS ( 2 , dofindleak ( " ;alloc; \n if assign; \n dealloc; " ) ) ;
2009-08-23 15:48:25 +02:00
2009-08-25 22:18:22 +02:00
// loop..
2009-10-18 13:17:05 +02:00
TODO_ASSERT_EQUALS ( 1 , dofindleak ( " ; loop { alloc ; if break; dealloc ; } " ) ) ;
TODO_ASSERT_EQUALS ( 1 , dofindleak ( " ; loop { alloc ; if continue; dealloc ; } " ) ) ;
2009-12-26 17:49:05 +01:00
ASSERT_EQUALS ( notfound , dofindleak ( " ; loop { alloc ; if break; } dealloc ; " ) ) ;
2009-08-25 22:18:22 +02:00
ASSERT_EQUALS ( 1 , dofindleak ( " ; loop alloc ; " ) ) ;
ASSERT_EQUALS ( 1 , dofindleak ( " ; loop alloc ; dealloc ; " ) ) ;
2010-07-30 08:50:10 +02:00
// callfunc (might be noreturn)
ASSERT_EQUALS ( notfound , dofindleak ( " ; alloc ; callfunc ; } " ) ) ;
2009-08-23 15:48:25 +02:00
}
2008-12-18 22:28:57 +01:00
2009-08-23 11:26:17 +02:00
2008-12-18 22:28:57 +01:00
void simple5 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static char *f() \n "
" { \n "
" struct *str = new strlist; \n "
" return &str->s; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void simple7 ( )
{
// A garbage collector may delete f automaticly
2009-01-05 16:49:57 +01:00
check ( " class Fred; \n "
" void foo() \n "
" { \n "
" Fred *f = new Fred; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void simple9 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" MyClass *c = new MyClass(); \n "
" c->free(c); \n "
" delete c; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-06-17 21:42:49 +02:00
void simple11 ( )
{
check ( " void Fred::aaa() \n "
" { } \n "
" \n "
" void Fred::foo() \n "
" { \n "
" char *s = NULL; \n "
" if (a) \n "
" s = malloc(10); \n "
" else if (b) \n "
" s = malloc(10); \n "
" else \n "
" f(); \n "
" g(s); \n "
" if (c) \n "
" h(s); \n "
" free(s); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-06-05 06:03:48 +02:00
void new_nothrow ( )
{
check ( " void f() \n "
" { \n "
" int *p = new(std::nothrow) int; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: p \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" using std::nothrow; \n "
" int *p = new(nothrow) int; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
2009-06-05 06:03:48 +02:00
check ( " void f() \n "
" { \n "
" int *p = new(std::nothrow) int[10]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
2009-06-05 06:03:48 +02:00
check ( " void f() \n "
" { \n "
" using namespace std; \n "
" int *p = new(nothrow) int[10]; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int *p = new(std::nothrow) int; \n "
" delete [] p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Mismatching allocation and deallocation: p \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" int *p = new(std::nothrow) int[10]; \n "
" delete p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Mismatching allocation and deallocation: p \n " , errout . str ( ) ) ;
2010-07-05 14:01:25 +02:00
check ( " void f() \n "
" { \n "
" Fred *f = new(nothrow) Fred; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" Fred *f = new(std::nothrow) Fred; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-05 06:03:48 +02:00
}
2008-12-18 22:28:57 +01:00
2009-07-06 12:20:13 +02:00
void staticvar ( )
{
check ( " int f() \n "
" { \n "
" static char *s = 0; \n "
" free(s); \n "
" s = malloc(100); \n "
" return 123; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-10-04 14:24:41 +02:00
void externvar ( )
{
check ( " void f() \n "
" { \n "
" extern char *s; \n "
" s = malloc(100); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-07-06 12:20:13 +02:00
2009-02-07 10:44:57 +01:00
void alloc_alloc_1 ( )
{
check ( " void foo() \n "
" { \n "
" char *str; \n "
" str = new char[10]; \n "
" str = new char[20]; \n "
" delete [] str; \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: str \n " , errout . str ( ) ) ;
2009-02-07 10:44:57 +01:00
}
2008-12-18 22:28:57 +01:00
void ifelse6 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static char *f() \n "
" { \n "
" char *s = new char[100]; \n "
" if ( a == b ) \n "
" { \n "
" return s; \n "
" } \n "
" return NULL; \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: s \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void ifelse7 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static char *f() \n "
" { \n "
" char *s; \n "
" if ( abc ) \n "
" { \n "
" s = new char[10]; \n "
" } \n "
" return s; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void ifelse8 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static char *f() \n "
" { \n "
" char *s = new char[10]; \n "
" if ( s ) \n "
" { \n "
" return s; \n "
" } \n "
" return 0; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-02-25 20:20:23 +01:00
void ifelse10 ( )
{
check ( " static char *f() \n "
" { \n "
" char *s = new char[10]; \n "
" if ( ghfgf ) \n "
" { \n "
" str[0] = s; \n "
" } \n "
" else \n "
" { \n "
" str[0] = s; \n "
" } \n "
" } \n " , true ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-25 20:20:23 +01:00
}
2008-12-18 22:28:57 +01:00
void if4 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void f() \n "
" { \n "
" char *s; \n "
" bool b = true; \n "
" if (b && (s = malloc(256))) \n "
" ; \n "
" if (b) \n "
" free(s); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void if7 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void f( bool b ) \n "
" { \n "
" int *a=0; \n "
" if( b ) \n "
" { \n "
" a = new int[10]; \n "
" } \n "
" \n "
" if( b ) \n "
" delete [] a; \n "
" else {} \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2008-12-22 15:42:54 +01:00
void if8 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void f(int i) \n "
" { \n "
" char *c = malloc(50); \n "
" if (i == 1) \n "
" { \n "
" free(c); \n "
" return; \n "
" } \n "
" if (i == 2) \n "
" { \n "
" return; \n "
" } \n "
" free(c); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: c \n " , errout . str ( ) ) ;
2008-12-22 15:42:54 +01:00
}
2009-01-02 08:44:49 +01:00
void if9 ( )
2008-12-18 22:28:57 +01:00
{
2009-01-05 16:49:57 +01:00
check ( " static void f() \n "
" { \n "
2009-03-23 18:34:59 +01:00
" char *buf = NULL, *tmp; \n "
" if (!(tmp = realloc(buf, 50))) \n "
" { \n "
" free(buf); \n "
" return NULL; \n "
" } \n "
" buf = tmp; \n "
" return buf; \n "
2009-01-05 16:49:57 +01:00
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-02 09:16:32 +01:00
void if10 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void f() \n "
" { \n "
2009-03-23 18:34:59 +01:00
" char *buf = malloc(10); \n "
" if (aa) \n "
" ; \n "
2009-01-05 16:49:57 +01:00
" else if (buf = realloc(buf, 100)) \n "
2009-03-23 18:34:59 +01:00
" ; \n "
2009-01-05 16:49:57 +01:00
" free(buf); \n "
" } \n " ) ;
2010-07-07 20:28:15 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Common realloc mistake: \" buf \" nulled but not freed upon failure \n " , errout . str ( ) ) ;
2009-01-02 09:16:32 +01:00
}
2009-02-04 07:11:36 +01:00
void if11 ( )
{
check ( " void foo() \n "
" { \n "
" int *x = new int[10]; \n "
" if (x == 0 || aa) \n "
" { \n "
" return 1; \n "
" } \n "
" delete [] x; \n "
" } \n " , true ) ;
2010-03-13 17:11:48 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:6]: (error) Memory leak: x \n " , errout . str ( ) ) ;
2010-08-05 13:30:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-04 07:11:36 +01:00
}
2008-12-18 22:28:57 +01:00
2009-01-02 08:44:49 +01:00
2008-12-18 22:28:57 +01:00
void forwhile5 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void f(const char **a) \n "
" { \n "
" char *str = 0; \n "
" for (int i = 0; i < 10 && !str; ++i) \n "
" { \n "
" str = strdup(a[i]); \n "
" } \n "
" return str; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void forwhile6 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void f(const char **a) \n "
" { \n "
" char *str = 0; \n "
" for (int i = 0; i < 10 && !str; ++i) \n "
" { \n "
" str = strdup(a[i]); \n "
" } \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: str \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void forwhile8 ( )
{
check ( " char *f() \n "
" { \n "
" char *a = 0; \n "
" int i = 0; \n "
" for( ;; ) \n "
" { \n "
2009-01-01 23:22:28 +01:00
" ++i; \n "
2008-12-18 22:28:57 +01:00
" a = realloc( a, i ); \n "
" if( !a ) \n "
" return 0; \n "
" \n "
" if( i > 10 ) \n "
" break; \n "
" } \n "
" \n "
" return a; \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2010-08-05 13:30:07 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Common realloc mistake: \" a \" nulled but not freed upon failure \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-10 17:28:04 +01:00
void forwhile9 ( )
{
check ( " char *f() \n "
" { \n "
" char *a = 0; \n "
" int i = 0; \n "
2009-04-05 01:55:45 +02:00
" for(i = 0 ;i < 50 ; i++) \n "
2009-01-10 17:28:04 +01:00
" { \n "
2009-04-05 01:55:45 +02:00
" if(func1(i)) \n "
" continue; \n "
" a = realloc( a, i ); \n "
" if(func2(i)) \n "
" continue; \n "
2009-01-10 17:28:04 +01:00
" } \n "
" \n "
" return a; \n "
" } \n " , true ) ;
2010-07-07 20:28:15 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Common realloc mistake: \" a \" nulled but not freed upon failure \n " , errout . str ( ) ) ;
2009-01-10 17:28:04 +01:00
}
void forwhile10 ( )
{
check ( " char *f() \n "
" { \n "
" char *a = 0; \n "
" int i = 0; \n "
2009-04-05 01:55:45 +02:00
" for(i = 0; i < 50; i++) \n "
2009-01-10 17:28:04 +01:00
" { \n "
2009-04-05 01:55:45 +02:00
" if(func1(i)) \n "
" continue; \n "
" a = realloc( a, i ); \n "
" if(func2(i)) \n "
" return; \n "
2009-01-10 17:28:04 +01:00
" } \n "
" \n "
" return a; \n "
" } \n " , true ) ;
2010-07-07 20:28:15 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Common realloc mistake: \" a \" nulled but not freed upon failure \n "
2010-05-18 07:46:48 +02:00
" [test.cpp:11]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2009-01-10 17:28:04 +01:00
}
2009-06-20 13:58:30 +02:00
void forwhile11 ( )
{
check ( " int main() \n "
" { \n "
" FILE *stream=NULL; \n "
" while((stream = fopen(name, \" r \" )) == NULL) \n "
" { } \n "
" if(stream!=NULL) fclose(stream); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
void switch2 ( )
{
2009-01-07 18:49:21 +01:00
const std : : string code ( " void f() \n "
" { \n "
" char *str = new char[10]; \n "
" switch (abc) \n "
" { \n "
" case 1: \n "
" delete [] str; \n "
" break; \n "
" default: \n "
" break; \n "
" }; \n "
" } \n " ) ;
check ( code . c_str ( ) , false ) ;
2010-05-31 18:20:34 +02:00
ASSERT_EQUALS ( " [test.cpp:12]: (error) Memory leak: str \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-17 08:55:40 +01:00
void switch3 ( )
{
check ( " void f() \n "
" { \n "
" char *str = new char[10]; \n "
" while (abc) \n "
" { \n "
" switch (def) \n "
" { \n "
" default: \n "
" return; \n "
" } \n "
" } \n "
" delete [] str; \n "
" } \n " ) ;
2009-02-05 22:06:32 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Memory leak: str \n " , errout . str ( ) ) ;
2009-01-17 08:55:40 +01:00
}
2008-12-18 22:28:57 +01:00
2008-12-25 09:27:07 +01:00
void ret5 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static char * f() \n "
" { \n "
" char *c = new char[50]; \n "
" return (c ? c : NULL); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-25 09:27:07 +01:00
}
2009-02-24 07:23:21 +01:00
void ret6 ( )
{
check ( " void foo() \n "
" { \n "
" char *c = new char[50]; \n "
" return strcpy(c, \" foo \" ); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-24 07:23:21 +01:00
}
2009-03-03 21:39:17 +01:00
void ret7 ( )
{
check ( " void foo() \n "
" { \n "
" char *c = new char[50]; \n "
" return memcpy(c, \" foo \" ,4); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-03 21:39:17 +01:00
}
2008-12-25 09:27:07 +01:00
2009-06-05 08:56:46 +02:00
void ret8 ( )
{
check ( " char *foo() \n "
" { \n "
" char *c = new char[50]; \n "
" return ((char *)(c+1)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-25 09:27:07 +01:00
2008-12-18 22:28:57 +01:00
void mismatch1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void f() \n "
" { \n "
" int *a = new int[10]; \n "
" free(a); \n "
2009-01-31 18:54:31 +01:00
" } \n " , true ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Mismatching allocation and deallocation: a \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-31 12:51:47 +01:00
void mismatch2 ( )
{
check ( " void f() \n "
" { \n "
2009-02-02 06:58:50 +01:00
" FILE *fp; \n "
2009-01-31 12:51:47 +01:00
" \n "
2009-02-02 06:58:50 +01:00
" fp = fopen(); \n "
" fclose(fp); \n "
2009-01-31 12:51:47 +01:00
" \n "
2009-02-02 06:58:50 +01:00
" fp = popen(); \n "
" pclose(fp); \n "
2009-01-31 18:54:31 +01:00
" } \n " , false ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-31 12:51:47 +01:00
}
2008-12-18 22:28:57 +01:00
2009-02-02 06:58:50 +01:00
void mismatch3 ( )
{
check ( " void f() \n "
" { \n "
" FILE *fp; \n "
" \n "
" if (abc) fp = fopen(); \n "
" else fp = popen(); \n "
" \n "
" if (abc) fclose(fp); \n "
" else pclose(fp); \n "
" } \n " , false ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-02 06:58:50 +01:00
}
void mismatch4 ( )
{
check ( " void f() \n "
" { \n "
" char *p = 0; \n "
" for (i = 0; i < 10; ++i) \n "
" { \n "
" delete p; \n "
" p = new char[100]; \n "
" } \n "
" delete [] p; \n "
" } \n " , false ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Mismatching allocation and deallocation: p \n " , errout . str ( ) ) ;
2009-02-02 06:58:50 +01:00
}
2008-12-18 22:28:57 +01:00
////////////////////////////////////////////////
// function calls
////////////////////////////////////////////////
void func3 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void foo(const char *str) \n "
" { } \n "
" \n "
" static void f() \n "
" { \n "
" char *p = new char[100]; \n "
" foo(p); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void func4 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void foo(char *str) \n "
" { \n "
" delete [] str; \n "
" } \n "
" \n "
" static void f() \n "
" { \n "
" char *p = new char[100]; \n "
" foo(p); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void func5 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void foo(char *str) \n "
" { \n "
" delete str; \n "
" } \n "
" \n "
" static void f() \n "
" { \n "
" char *p = new char[100]; \n "
" foo(p); \n "
2009-01-31 18:54:31 +01:00
" } \n " , true ) ;
2009-06-14 07:33:46 +02:00
ASSERT_EQUALS ( " [test.cpp:9] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: str \n " ,
errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void func6 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void foo(char *str) \n "
" { \n "
" goto abc; \n "
" } \n "
" \n "
" static void f() \n "
" { \n "
" char *p = new char[100]; \n "
" foo(p); \n "
" } \n " ) ;
2009-06-14 07:33:46 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void func7 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void foo(char *str) \n "
" { \n "
" if (abc) \n "
" return; "
" delete [] str; \n "
" } \n "
" \n "
" static void f() \n "
" { \n "
" char *p = new char[100]; \n "
" foo(p); \n "
" } \n " ) ;
2009-06-14 07:33:46 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2010-08-05 13:30:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void func9 ( )
{
2009-01-05 16:49:57 +01:00
check ( " int b() \n "
" { \n "
" return 0; \n "
" } \n "
" \n "
" void a() \n "
" { \n "
" char *a = new char[10]; \n "
" if (b()) \n "
" return; \n "
" delete [] a; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2008-12-25 08:50:25 +01:00
void func10 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void f(void (*fnc)(char*)) \n "
" { \n "
" char *c = malloc(50); \n "
" (fnc)(c); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-25 08:50:25 +01:00
}
2009-01-02 01:05:08 +01:00
void func11 ( )
{
2009-01-05 16:49:57 +01:00
check ( " static void f(struct1 *s1) \n "
" { \n "
" char *c = malloc(50); \n "
" (s1->fnc)(c); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-02 01:05:08 +01:00
}
2009-01-03 08:40:09 +01:00
void func12 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void add_list(struct mmtimer *n) \n "
" { \n "
" rb_link_node(&n->list, parent, link); \n "
" } \n "
" \n "
" int foo() \n "
" { \n "
" struct mmtimer *base; \n "
" \n "
" base = kmalloc(sizeof(struct mmtimer), GFP_KERNEL); \n "
" if (base == NULL) \n "
" return -ENOMEM; \n "
" \n "
" add_list(base); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-03 08:40:09 +01:00
}
2009-01-24 19:55:56 +01:00
void func13 ( )
{
check ( " static void f() \n "
" { \n "
" char *p = malloc(100); \n "
" foo(&p); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-24 19:55:56 +01:00
}
2009-06-12 17:31:29 +02:00
void func14 ( )
{
// It is not known what the "foo" that only takes one parameter does..
check ( " static void foo(char *a, char *b) \n "
" { \n "
" free(a); \n "
" free(b); \n "
" } \n "
" static void f() \n "
" { \n "
" char *p = malloc(100); \n "
" foo(p); \n "
" free(p); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-01-24 19:55:56 +01:00
2009-06-16 19:05:05 +02:00
void func15 ( )
{
check ( " static void a() \n "
" { return true; } \n "
" \n "
" static void b() \n "
" { \n "
" char *p = malloc(100); \n "
" if (a()) return; \n " // <- memory leak
" free(p); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2009-08-18 20:49:08 +02:00
void func16 ( )
{
check ( " static void a( bo_t *p_bo) \n "
" { \n "
" p_bo->buffer = realloc( p_bo->buffer, 100 ); \n "
" } \n "
" \n "
" static bo_t * b() \n "
" { \n "
" bo_t *box; \n "
" if( ( box = malloc( sizeof( bo_t ) ) ) ) \n "
" { \n "
" a(box); \n "
" a(box); \n "
" } \n "
" return box; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-06-16 19:05:05 +02:00
2010-02-06 22:35:36 +01:00
void func17 ( )
{
// The "bar" function must be reduced to "use"
check ( " bool bar(char **parent, char *res, bool a) \n "
" { \n "
" if( a ) \n "
" { \n "
" *parent = res; \n "
" return false; \n "
" } \n "
" return true; \n "
" } \n "
" \n "
" void foo(char **parent, bool a) \n "
" { \n "
" if (a) \n "
" { \n "
" char *res = malloc(65); \n "
" bar(parent, res, a); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-05-30 20:30:08 +02:00
void func18 ( )
{
// No false positive
// The "free_pointers" will deallocate all pointers
check ( " static void free_pointers(int arg_count, ...) \n "
" { \n "
" va_list a; \n "
" va_start(a, arg_count); \n "
" for (int i = 0; i < arg_count; i++) \n "
" { \n "
" free(va_arg(a, void *)); \n "
" } \n "
" va_end(a); \n "
" } \n "
" \n "
" static char* foo() \n "
" { \n "
" return strdup( " " ); \n "
" } \n "
" \n "
" static void bar() \n "
" { \n "
" int *p = malloc(16); \n "
" free_pointers(1, p); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-09-19 12:16:29 +02:00
void func19 ( )
{
// Ticket #2056
check ( " bool a(int *p) { \n "
" return p; \n "
" } \n "
" \n "
" void b() { \n "
" int *p = malloc(16); \n "
" if (!a(p)) return; \n "
" free(p); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-11-10 18:24:40 +01:00
void func20 ( )
{
// Ticket #2182 - false positive when there is unused class.
// If the unused class is removed the false positive goes away.
// [test.cpp:12]: (error) Deallocating a deallocated pointer: p
check ( " class test { \n "
" void f(); \n "
" }; \n "
" void test::f() { } \n "
" \n "
" void b(int i) { \n "
" char *p = new char[10]; \n "
" if (i) { \n "
" delete [] p; \n "
" exit(0); \n "
" } \n "
" delete [] p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// False positive in classmember
// same code as above but the implementation is used in the
// class member function
check ( " class test { \n "
" void f(int i); \n "
" }; \n "
" void test::f(int i) { \n "
" char *p = new char[10]; \n "
" if (i) { \n "
" delete [] p; \n "
" exit(0); \n "
" } \n "
" delete [] p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-05-30 20:30:08 +02:00
2008-12-18 22:28:57 +01:00
2009-06-15 17:44:59 +02:00
void allocfunc1 ( )
{
check ( " static char *a() \n "
" { \n "
" return new char[100]; \n "
" } \n "
" static void b() \n "
" { \n "
" char *p = a(); \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " [test.cpp:8]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
2009-10-06 22:14:32 +02:00
check ( " FILE *a() \n "
" { \n "
" return fopen( \" test.txt \" , \" w \" ); \n "
" } \n "
" static void b() \n "
" { \n "
" FILE *p = a(); \n "
" } \n " ) ;
2010-05-09 13:46:13 +02:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:8]: (error) Resource leak: p \n " ) , errout . str ( ) ) ;
2009-10-06 22:14:32 +02:00
check ( " char *a() \n "
" { \n "
" return malloc(10); \n "
" } \n "
" static void b() \n "
" { \n "
" char *p = a(); \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " [test.cpp:8]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
2009-06-15 17:44:59 +02:00
}
2008-12-18 22:28:57 +01:00
2009-08-05 21:18:16 +02:00
void allocfunc2 ( )
{
check ( " static char *a(int size) \n "
" { \n "
" return new char[size]; \n "
" } \n "
" static void b() \n "
" { \n "
" int len = 100; \n "
" char *p = a(len); \n "
" delete [] p; \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
2009-10-06 22:14:32 +02:00
check ( " char *a(char *a) \n "
" { \n "
" return realloc(a, 10); \n "
" } \n "
" static void b() \n "
" { \n "
" char *p = a(0); \n "
2010-05-10 18:11:02 +02:00
" char *q = a(p); \n "
" if (q) \n "
" free(q); \n "
" else \n "
" free(p); \n "
2009-10-06 22:14:32 +02:00
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
check ( " char *a() \n "
" { \n "
" return malloc(10); \n "
" } \n "
" static void b() \n "
" { \n "
" char *p = a(); \n "
" free(p); \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
2009-08-05 21:18:16 +02:00
}
2010-04-24 20:40:57 +02:00
void allocfunc3 ( )
{
check ( " static char *a() \n "
" { \n "
" char *data = malloc(10);; "
" return data; \n "
" } \n "
" static void b() \n "
" { \n "
" char *p = a(); \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " [test.cpp:8]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
2010-05-09 13:46:13 +02:00
void allocfunc4 ( )
{
check ( " char* foo() \n "
" { \n "
" char *str = NULL; \n "
" str = realloc( str, 20 ); \n "
" return str; \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *p = foo(); \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " [test.cpp:11]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
check ( " char* foo() \n "
" { \n "
" char *str = NULL; \n "
" str = realloc( str, 20 ); \n "
" return str; \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *p = foo(); \n "
" delete p; \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " [test.cpp:11]: (error) Mismatching allocation and deallocation: p \n " ) , errout . str ( ) ) ;
}
2010-06-05 01:58:50 +02:00
void allocfunc5 ( )
{
check ( " void foo(char **str) \n "
" { \n "
" *str = malloc(20); \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *p; \n "
" foo(&p); \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " [test.cpp:10]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
check ( " void foo(char **str) \n "
" { \n "
" *str = malloc(20); \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *p; \n "
" foo(&p); \n "
" delete p; \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " [test.cpp:10]: (error) Mismatching allocation and deallocation: p \n " ) , errout . str ( ) ) ;
check ( " void foo(char **q, char **str) \n "
" { \n "
" *str = malloc(20); \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *p; \n "
" char *q; \n "
" foo(&q, &p); \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " [test.cpp:11]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
check ( " void foo(char **str) \n "
" { \n "
" char *a = malloc(20) \n "
" *str = a; \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *p; \n "
" foo(&p); \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( std : : string ( " [test.cpp:11]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
2010-08-05 13:30:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-17 03:29:55 +02:00
check ( " void foo(char **str) \n "
" { \n "
" free(*str); \n "
" *str = malloc(20); \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *tmp = malloc(10); \n "
" foo(&tmp); \n "
2010-06-17 03:46:47 +02:00
" foo(&tmp); \n "
2010-06-17 03:29:55 +02:00
" free(tmp); \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
2010-06-17 03:47:05 +02:00
//#ticket 1789: getcode other function:
check ( " void foo(char **str) \n "
" { \n "
" if (*str == NULL) \n "
" *str = malloc(20) \n ; "
" else \n "
" *str = realloc(*str, 20) \n ; "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *tmp = malloc(10); \n "
" foo(&tmp); \n "
" foo(&tmp); \n "
" free(tmp); \n "
" } \n " ) ;
2010-07-06 21:36:50 +02:00
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
2010-06-05 01:58:50 +02:00
}
2008-12-18 22:28:57 +01:00
2010-06-30 09:21:15 +02:00
void allocfunc6 ( )
{
check ( " static FILE* data() \n "
" { \n "
" return fopen( \" data.txt \" , \" rt \" ); \n "
" } \n "
" \n "
" static void foo() \n "
" { \n "
" char* expr; \n "
" func(&expr); \n "
" \n "
" FILE *f = data(); \n "
" fclose(f); \n "
" \n "
" free(expr); \n "
" } \n " ) ;
ASSERT_EQUALS ( std : : string ( " " ) , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
void throw1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *str = new char[10]; \n "
" if ( ! abc ) \n "
" throw 123; \n "
" delete [] str; \n "
" } \n " ) ;
2008-12-18 22:28:57 +01:00
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: str \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2008-12-27 12:29:38 +01:00
void throw2 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *str = 0; \n "
" try \n "
" { \n "
" str = new char[100]; \n "
" if ( somecondition ) \n "
" throw exception; \n "
" delete [] str; \n "
" } \n "
" catch ( ... ) \n "
" { \n "
" delete [] str; \n "
" } \n "
" } \n " ) ;
2008-12-27 12:29:38 +01:00
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-27 12:29:38 +01:00
}
2008-12-18 22:28:57 +01:00
void linux_list_1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " struct AB \n "
" { \n "
" int a; \n "
" int b; \n "
" }; \n "
" void foo() \n "
" { \n "
" struct AB *ab = new AB; \n "
" func(&ab->a); \n "
" } \n " ) ;
2008-12-18 22:28:57 +01:00
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void sizeof1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void f() \n "
" { \n "
" struct s_t s1; \n "
" struct s_t cont *p = &s1; \n "
" struct s_t *s2; \n "
" \n "
" memset(p, 0, sizeof(*p)); \n "
" \n "
" s2 = (struct s_t *) malloc(sizeof(*s2)); \n "
" \n "
" if (s2->value != 0) \n "
" return; \n "
" \n "
" free(s2); \n "
" \n "
" return; \n "
" } \n " ) ;
2008-12-18 22:28:57 +01:00
2009-06-14 07:33:46 +02:00
ASSERT_EQUALS ( " [test.cpp:12]: (error) Memory leak: s2 \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void realloc1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" a = realloc(a, 100); \n "
" } \n " ) ;
2010-07-07 20:28:15 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \" a \" nulled but not freed upon failure \n "
2010-05-18 07:46:48 +02:00
" [test.cpp:5]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void realloc2 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" a = (char *)realloc(a, 100); \n "
" free(a); \n "
" } \n " ) ;
2008-12-18 22:28:57 +01:00
2010-07-07 20:28:15 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \" a \" nulled but not freed upon failure \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-03-22 21:42:01 +01:00
void realloc3 ( )
{
check ( " void foo() \n "
" { \n "
" char *a = 0; \n "
" if ((a = realloc(a, 100)) == NULL) \n "
" return; \n "
" free(a); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-22 21:42:01 +01:00
}
2009-03-28 16:13:06 +01:00
void realloc4 ( )
{
check ( " void foo() \n "
" { \n "
" static char *a = 0; \n "
" if ((a = realloc(a, 100)) == NULL) \n "
" return; \n "
" free(a); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2010-08-05 13:30:07 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \" a \" nulled but not freed upon failure \n " , errout . str ( ) ) ;
2009-03-28 16:13:06 +01:00
}
2009-08-02 21:23:47 +02:00
void realloc5 ( )
{
check ( " void foo() \n "
" { \n "
2009-09-24 22:40:18 +02:00
" char *buf; \n "
" char *new_buf; \n "
" buf = calloc( 10 ); \n "
" new_buf = realloc ( buf, 20); \n "
" if ( !new_buf ) \n "
" free(buf); \n "
" else \n "
" free(new_buf); \n "
2010-05-16 19:55:16 +02:00
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-02 21:23:47 +02:00
}
2008-12-18 22:28:57 +01:00
2009-08-10 22:04:28 +02:00
void realloc6 ( )
{
2009-08-19 19:42:07 +02:00
ASSERT_EQUALS ( " ;;realloc;; " , getcode ( " char *buf; buf=realloc(buf,100); " , " buf " ) ) ;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " char *buf; buf=realloc(0,100); " , " buf " ) ) ;
2009-08-10 22:04:28 +02:00
}
2010-07-19 08:55:39 +02:00
void realloc7 ( )
{
check ( " bool foo(size_t nLen, char* pData) \n "
" { \n "
" pData = (char*) realloc(pData, sizeof(char) + (nLen + 1)*sizeof(char)); \n "
" if ( pData == NULL ) \n "
" { \n "
" return false; \n "
" } \n "
" free(pData); \n "
" return true; \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-07-27 08:17:27 +02:00
void realloc8 ( )
{
check ( " void foo() \n "
" { \n "
" char *origBuf = m_buf; \n "
" m_buf = (char *) realloc (m_buf, m_capacity + growBy); \n "
" if (!m_buf) { \n "
" m_buf = origBuf; \n "
" } \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-08-24 20:58:22 +02:00
void realloc9 ( )
{
check ( " void foo() \n "
" { \n "
" x = realloc(x,100); \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-09-11 11:15:04 +02:00
void realloc10 ( )
{
check ( " void foo() { \n "
" char *pa, *pb; \n "
" pa = pb = malloc(10); \n "
" pa = realloc(pa, 20); "
" exit(); \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
void assign ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" a = 0; \n "
" free(a); \n "
" } \n " ) ;
2008-12-18 22:28:57 +01:00
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" char *p = a; \n "
" free(p); \n "
" } \n " ) ;
2008-12-18 22:28:57 +01:00
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-26 21:12:42 +01:00
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" char *p = a + 1; \n "
" free(p); \n "
" } \n " ) ;
2008-12-26 21:12:42 +01:00
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" a += 10; \n "
" free(a - 10); \n "
" } \n " ) ;
2008-12-18 22:28:57 +01:00
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" a = (void *)a + 10; \n "
" free(a - 10); \n "
" } \n " ) ;
2008-12-18 22:28:57 +01:00
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-28 21:57:50 +01:00
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *a = new char[100]; \n "
" list += a; \n "
" } \n " ) ;
2008-12-28 21:57:50 +01:00
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void varid ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *p = malloc(100); \n "
" { \n "
" char *p = 0; \n "
" delete p; \n "
" } \n "
" free(p); \n "
" } \n " ) ;
2009-08-19 19:42:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
void cast1 ( )
{
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *a = reinterpret_cast<char *>(malloc(10)); \n "
" } \n " ) ;
2008-12-18 22:28:57 +01:00
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-07-21 13:04:13 +02:00
void dealloc_use ( )
2008-12-18 22:28:57 +01:00
{
2009-07-21 13:04:13 +02:00
// It is ok to take the address..
2009-01-05 16:49:57 +01:00
check ( " void f() \n "
" { \n "
2009-07-21 13:04:13 +02:00
" char *s = new char[100]; \n "
" delete [] s; \n "
" p = s; \n "
2009-01-05 16:49:57 +01:00
" } \n " ) ;
2009-07-21 13:04:13 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
check ( " void f() \n "
" { \n "
" char *s = new char[100]; \n "
" delete [] s; \n "
2009-07-21 13:04:13 +02:00
" foo(s); \n "
2009-01-05 16:49:57 +01:00
" } \n " ) ;
2009-07-21 13:04:13 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-31 10:02:45 +01:00
2009-07-21 13:04:13 +02:00
// The pointer to the pointer is valid..
2009-01-05 16:49:57 +01:00
check ( " void f() \n "
" { \n "
" char *str; \n "
" free(str); \n "
" foo(&str); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-01 09:15:27 +01:00
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
" char *str = 0; \n "
" free(str); \n "
" f1(&str); \n "
" f2(str); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-01 11:14:52 +01:00
2009-07-21 13:04:13 +02:00
// Dereferencing the freed pointer is not ok..
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
2009-03-25 07:10:17 +01:00
" char *str = malloc(10); \n "
2009-01-05 16:49:57 +01:00
" free(str); \n "
2009-07-21 13:04:13 +02:00
" char c = *str; \n "
2009-01-05 16:49:57 +01:00
" } \n " ) ;
2009-07-21 13:04:13 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released \n " , errout . str ( ) ) ;
2010-08-05 13:30:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-02 09:00:12 +01:00
2009-01-05 16:49:57 +01:00
check ( " void foo() \n "
" { \n "
2009-07-21 13:04:13 +02:00
" char *str = malloc(10); \n "
2009-01-05 16:49:57 +01:00
" free(str); \n "
2009-07-21 13:04:13 +02:00
" char c = str[10]; \n "
2009-01-05 16:49:57 +01:00
" } \n " ) ;
2009-07-21 13:04:13 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released \n " , errout . str ( ) ) ;
2009-01-03 08:47:35 +01:00
2009-02-05 21:17:01 +01:00
check ( " void foo() \n "
" { \n "
2009-07-21 13:04:13 +02:00
" char *str = malloc(10); \n "
" free(str); \n "
2009-02-05 21:17:01 +01:00
" str[10] = 0; \n "
" } \n " ) ;
2009-07-21 13:04:13 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released \n " , errout . str ( ) ) ;
2010-10-25 17:36:46 +02:00
check ( " void foo() { \n "
" char *str = malloc(10); \n "
" free(str); \n "
" strcpy(str, p); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dereferencing 'str' after it is deallocated / released \n " , errout . str ( ) ) ;
2010-10-26 17:49:48 +02:00
check ( " void foo(int x) { \n "
" char *str = malloc(10); \n "
" free(str); \n "
" assert(x); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-05 21:17:01 +01:00
}
2009-01-15 21:34:39 +01:00
2009-01-16 17:29:41 +01:00
void freefree1 ( )
2009-01-15 21:34:39 +01:00
{
check ( " void foo() \n "
" { \n "
" char *str = malloc(100); \n "
" free(str); \n "
" free(str); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Deallocating a deallocated pointer: str \n " , errout . str ( ) ) ;
2009-01-15 21:34:39 +01:00
}
2009-01-16 17:29:41 +01:00
void freefree2 ( )
{
check ( " void foo() \n "
" { \n "
" FILE *fd = fopen( \" test.txt \" , \" wb \" ); \n "
" fprintf(fd, \" test \" ); \n "
" fclose(fd); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-16 17:29:41 +01:00
}
2009-06-06 20:55:16 +02:00
void strcpy_result_assignment ( )
{
check ( " void foo() \n "
" { \n "
" char *p1 = malloc(10); \n "
" char *p2 = strcpy(p1, \" a \" ); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-01-25 16:56:19 +01:00
void strcat_result_assignment ( )
{
2009-02-07 10:44:57 +01:00
check ( " void foo() \n "
2009-01-25 16:56:19 +01:00
" { \n "
2009-02-07 10:44:57 +01:00
" char *p = malloc(10); \n "
" p[0] = 0; \n "
" p = strcat( p, \" a \" ); \n "
" free( p ); \n "
" return 0; \n "
2009-01-25 16:56:19 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-25 16:56:19 +01:00
}
2009-01-31 14:57:27 +01:00
void all1 ( )
{
check ( " void foo() \n "
" { \n "
" Fred *f = new Fred; \n "
" } \n " , false ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-31 14:57:27 +01:00
}
2009-02-07 11:54:39 +01:00
void malloc_constant_1 ( )
{
check ( " void foo() \n "
" { \n "
" int *p = malloc(3); \n "
" free(p); \n "
" } \n " , false ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) The given size 3 is mismatching \n " , errout . str ( ) ) ;
2009-02-07 11:54:39 +01:00
}
2009-02-08 09:21:15 +01:00
void unknownFunction1 ( )
{
2009-02-08 12:59:04 +01:00
check ( " void foo() \n "
" { \n "
" int *p = new int[100]; \n "
" if (abc) \n "
" { \n "
" delete [] p; \n "
" ThrowException(); \n "
" } \n "
" delete [] p; \n "
" } \n " ) ;
2009-02-08 09:21:15 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-08 12:59:04 +01:00
}
void unknownFunction2 ( )
{
check ( " void foo() \n "
" { \n "
" int *p = new int[100]; \n "
" if (abc) \n "
" { \n "
" delete [] p; \n "
" ThrowException(); \n "
" } \n "
" } \n " ) ;
2009-02-08 19:27:09 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-06-03 22:20:33 +02:00
check ( " void foo() \n "
" { \n "
" int *p = new int[100]; \n "
" p = g(); \n "
" delete [] p; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-02-08 09:21:15 +01:00
}
2009-06-21 13:48:39 +02:00
void unknownFunction4 ( )
{
check ( " void foo() \n "
" { \n "
" int *p = new int[100]; \n "
" a(); \n "
" if (b) return; \n "
" delete [] p; \n "
2009-06-21 14:12:59 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-06-21 13:48:39 +02:00
}
2009-06-23 18:29:43 +02:00
void unknownFunction5 ( )
{
check ( " static void foo() \n "
" { \n "
" char *p = NULL; \n "
" \n "
" if( a ) \n "
" p = malloc(100); \n "
" \n "
" if( a ) \n "
" { \n "
" FREENULL(p); \n "
" FREENULL(); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-20 07:28:18 +01:00
2010-05-16 07:15:31 +02:00
void checkvcl ( const char code [ ] )
2009-02-20 07:28:18 +01:00
{
// Clear the error buffer..
errout . str ( " " ) ;
2010-04-17 09:23:54 +02:00
Settings settings ;
settings . inconclusive = true ;
2009-03-06 18:13:41 +01:00
2010-12-01 18:00:55 +01:00
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . setVarId ( ) ;
tokenizer . simplifyTokenList ( ) ;
// Check for memory leaks..
2009-06-08 20:20:43 +02:00
CheckMemoryLeakInFunction checkMemoryLeak ( & tokenizer , & settings , this ) ;
checkMemoryLeak . check ( ) ;
2009-02-23 20:32:54 +01:00
}
2009-12-30 21:29:54 +01:00
void class1 ( )
{
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred() \n "
" { \n "
" int *p = new int[100]; \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2009-04-28 20:01:35 +02:00
void autoptr1 ( )
{
check ( " std::auto_ptr<int> foo() \n "
" { \n "
" int *i = new int; \n "
" return std::auto_ptr<int>(i); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-06-08 20:20:43 +02:00
void if_with_and ( )
2009-04-29 20:40:21 +02:00
{
2009-06-08 20:20:43 +02:00
check ( " void f() \n "
2009-04-29 20:40:21 +02:00
" { \n "
2009-06-08 20:20:43 +02:00
" char *a = new char[10]; \n "
" if (!a && b() ) \n "
" return; \n "
2009-05-01 11:29:49 +02:00
" \n "
" delete [] a; \n "
" } \n " , true ) ;
2009-05-01 11:28:33 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-01 11:29:49 +02:00
check ( " void f() \n "
" { \n "
" char *a = new char[10]; \n "
" if (b() && !a ) \n "
" return; \n "
" \n "
" delete [] a; \n "
" } \n " , true ) ;
2009-05-01 13:39:57 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-01 11:28:33 +02:00
}
2009-05-06 20:20:25 +02:00
void assign_pclose ( )
{
check ( " void f() \n "
" { \n "
" FILE *f = popen ( \" test \" , \" w \" ); \n "
" int a = pclose(f); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-06 20:20:25 +02:00
}
2009-05-10 08:01:38 +02:00
void exit2 ( )
{
check ( " void f() \n "
" { \n "
" char *out = new char[100]; \n "
" exit(0); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-07 08:55:20 +02:00
check ( " void f() \n "
" { \n "
" char *out = new char[100]; \n "
" if( out ) {} \n "
" exit(0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-10 08:01:38 +02:00
}
2009-05-12 21:04:49 +02:00
2009-07-23 16:30:30 +02:00
void exit4 ( )
{
check ( " void f() \n "
" { \n "
" char *p = malloc(100); \n "
" if (x) \n "
" { \n "
" exit(0); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2009-08-04 21:34:14 +02:00
void exit5 ( )
{
check ( " void f() \n "
" { \n "
" char *p = malloc(100); \n "
" if (p) \n "
" { \n "
" xyz(); \n "
" exit(0); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-12-03 19:19:20 +01:00
void exit6 ( )
{
check ( " int main(int argc, char *argv[]) { \n "
" FILE *sfile; \n "
" unsigned long line; \n "
" sfile = fopen( \" bar \" , \" r \" ); \n "
" if (!sfile) \n "
" return 1; \n "
" for(line = 0; ; line++) { \n "
" if (argc > 3) \n "
" break; \n "
" exit(0); \n "
" } \n "
" fclose(sfile); \n "
" exit(0); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-11-14 09:06:28 +01:00
void noreturn ( )
{
check ( " void fatal_error() \n "
" { exit(1); } \n "
" \n "
" void f() \n "
" { \n "
" char *p = malloc(100); \n "
" fatal_error(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-07-23 16:30:30 +02:00
2009-05-12 21:04:49 +02:00
void stdstring ( )
{
check ( " void f(std::string foo) \n "
" { \n "
" char *out = new char[11]; \n "
" memset(&(out[0]), 0, 1); \n "
" } \n " ) ;
2009-06-14 07:33:46 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: out \n " , errout . str ( ) ) ;
2009-05-12 21:04:49 +02:00
}
2009-05-19 22:29:10 +02:00
void strndup_function ( )
{
check ( " void f() \n "
" { \n "
" char *out = strndup( \" text \" , 3); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: out \n " , errout . str ( ) ) ;
2009-05-19 22:29:10 +02:00
}
2009-06-01 12:40:24 +02:00
void tmpfile_function ( )
{
check ( " void f() \n "
" { \n "
" FILE *f = tmpfile(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: f \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" FILE *f = tmpfile(); \n "
" if (!f) \n "
" return; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Resource leak: f \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" FILE *f = tmpfile(); \n "
" fclose(f); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" FILE *f = tmpfile(); \n "
" if (!f) \n "
" return; \n "
" fclose(f); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " FILE *f() \n "
" { \n "
" return tmpfile(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-05-22 16:47:40 +02:00
void fcloseall_function ( )
{
check ( " void f() \n "
" { \n "
" FILE *f = fopen(fname, str); \n "
" fcloseall(); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-01 12:40:24 +02:00
check ( " void f() \n "
" { \n "
" FILE *f = tmpfile(); \n "
" fcloseall(); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-22 16:47:40 +02:00
}
2009-06-21 17:01:43 +02:00
void open_function ( )
{
check ( " void f(const char *path) \n "
" { \n "
" int fd = open(path, O_RDONLY); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: fd \n " , errout . str ( ) ) ;
check ( " void f(const char *path) \n "
" { \n "
" int fd = open(path, O_RDONLY); \n "
" if (fd == -1) \n "
" return; \n "
" close(fd); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const char *path) \n "
" { \n "
" int fd = open(path, O_RDONLY); \n "
" if (fd < 0) \n "
" return; \n "
" close(fd); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-11-30 16:45:19 +01:00
check ( " void f(const char *path) \n "
" { \n "
" int fd = open(path, O_RDONLY); \n "
" if (-1 == fd) \n "
" return; \n "
" close(fd); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-21 17:01:43 +02:00
}
void creat_function ( )
{
check ( " void f(const char *path) \n "
" { \n "
" int fd = creat(path, S_IRWXU); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: fd \n " , errout . str ( ) ) ;
}
void close_function ( )
{
check ( " void f(const char *path) \n "
" { \n "
" int fd = open(path, O_RDONLY); \n "
" close(fd); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const char *path) \n "
" { \n "
" int fd = creat(path, S_IRWXU); \n "
" close(fd); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const char *path) \n "
" { \n "
" int fd = creat(path, S_IRWXU); \n "
" if (close(fd) < 0) { \n "
" perror( \" close \" ); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-10 22:49:34 +02:00
//#ticket 1401
check ( " int myfunc() \n "
" { \n "
" int handle; \n "
" \n "
2010-10-21 22:33:40 +02:00
" handle = open( \" myfile \" ); \n "
2010-06-10 22:49:34 +02:00
" if (handle < 0) return 1; \n "
" \n "
" while (some_condition()) \n "
" if (some_other_condition()) \n "
" { \n "
" close(handle); \n "
" return 3; \n "
" } \n "
" close(handle); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
//#ticket 1401
check ( " int myfunc() \n "
" { \n "
" int handle; \n "
" \n "
2010-10-21 22:33:40 +02:00
" handle = open( \" myfile \" ); \n "
2010-06-10 22:49:34 +02:00
" if (handle < 0) return 1; \n "
" \n "
" while (some_condition()) \n "
" if (some_other_condition()) \n "
" { \n "
" return 3; \n "
" } \n "
" close(handle); \n "
" } \n " ) ;
2010-10-21 22:33:40 +02:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Resource leak: handle \n " , errout . str ( ) ) ;
2009-06-21 17:01:43 +02:00
}
void fd_functions ( )
{
check ( " void f(const char *path) \n "
" { \n "
" int fd = open(path, O_RDONLY); \n "
" read(fd, buf, count); \n "
" readv(fd, iov, iovcnt); \n "
" readahead(fd, offset, count); \n "
" pread(fd, buf, count, offset); \n "
" write(fd, buf, count); \n "
" writev(fd, iov, iovcnt); \n "
" pwrite(fd, buf, count, offset); \n "
" ioctl(fd, request); \n "
" posix_fallocate(fd, offset, len); \n "
" posix_fadvise(fd, offset, len, advise); \n "
" fsync(fd); \n "
" fdatasync(fd); \n "
" sync_file_range(fd, offset, nbytes, flags); \n "
" lseek(fd, offset, whence); \n "
" fcntl(fd, cmd); \n "
" flock(fd, op); \n "
" lockf(fd, cmd, len); \n "
" ftruncate(fd, len); \n "
" fstat(fd, buf); \n "
2009-07-18 18:48:48 +02:00
" fchmod(fd, mode); \n "
2009-06-21 17:01:43 +02:00
" } \n " ) ;
2009-07-18 18:48:48 +02:00
ASSERT_EQUALS ( " [test.cpp:24]: (error) Resource leak: fd \n " , errout . str ( ) ) ;
2009-06-21 17:01:43 +02:00
}
2009-05-22 09:24:03 +02:00
void opendir_function ( )
{
check ( " void f() \n "
" { \n "
" DIR *f = opendir( \" . \" ); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: f \n " , errout . str ( ) ) ;
2009-05-22 09:24:03 +02:00
}
void fdopendir_function ( )
{
check ( " void f(int fd) \n "
" { \n "
" DIR *f = fdopendir(fd); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: f \n " , errout . str ( ) ) ;
2009-05-22 09:24:03 +02:00
}
void closedir_function ( )
{
check ( " void f() \n "
" { \n "
" DIR *f = opendir( \" . \" ); \n "
" closedir(f); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-22 09:24:03 +02:00
check ( " void f(int fd) \n "
" { \n "
" DIR *f = fdopendir(fd); \n "
" closedir(f); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-22 09:24:03 +02:00
check ( " void foo() \n "
" { \n "
" DIR * f = opendir(dirname); \n "
" if (closedir(f)); \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-22 09:24:03 +02:00
}
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 " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Resource leak: f \n " , errout . str ( ) ) ;
2009-05-22 09:24:03 +02:00
}
2009-05-23 13:01:18 +02:00
void file_functions ( )
2009-05-23 12:20:26 +02:00
{
check ( " void f() \n "
" { \n "
" FILE *f = fopen(fname, str); \n "
" feof(f); \n "
2009-05-23 13:01:18 +02:00
" clearerr(in); \n "
" ferror(in); \n "
" fread(ptr, 10, 1, in); \n "
" fwrite(ptr, 10, 1, in); \n "
" fflush(in); \n "
" setbuf(in, buf); \n "
" setbuffer(in, buf, 100); \n "
" setlinebuf(in); \n "
" setvbuf(in, buf, _IOLBF, 0); \n "
" fseek(in, 10, SEEK_SET); \n "
" fseeko(in, 10, SEEK_SET); \n "
" ftell(in); \n "
" ftello(in); \n "
" rewind(in); \n "
" fsetpos(in, 0); \n "
" fgetpos(in, 10); \n "
" fprintf(in, \" text \\ n \" ); \n "
" } \n " ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:22]: (error) Resource leak: f \n " , errout . str ( ) ) ;
2009-05-23 12:20:26 +02:00
}
2009-07-18 20:35:22 +02:00
void getc_function ( )
{
2009-07-18 13:32:55 +02:00
{
check ( " void f() \n "
" { "
" int c; \n "
" FILE *fin1a = fopen ( \" FILE.txt \" , \" r \" ); \n "
" while ( (c = getc (fin1a)) != EOF) \n "
" { } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Resource leak: fin1a \n " , errout . str ( ) ) ;
}
{
check ( " void f() \n "
" { \n "
" int c; \n "
" FILE *fin1b = fopen( \" FILE.txt \" , \" r \" ); \n "
" c = getc(fin1b); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Resource leak: fin1b \n " , errout . str ( ) ) ;
}
}
2009-05-22 22:36:03 +02:00
void pointer_to_pointer ( )
{
check ( " void f(char **data) \n "
" { \n "
" char *c = new char[12]; \n "
" *c = 0; \n "
" *data = c; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-22 22:36:03 +02:00
}
2009-05-27 21:16:54 +02:00
void dealloc_and_alloc_in_func ( )
{
check ( " char *f( const char *x ) \n "
" { \n "
" delete [] x; \n "
" return new char[10]; \n "
" } \n "
" \n "
" int main() \n "
" { \n "
" char *a=0; \n "
" a = f( a ); \n "
" a[0] = 1; \n "
" delete [] a; \n "
" return 0; \n "
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-27 21:16:54 +02:00
}
2009-07-31 23:42:21 +02:00
void unknownSyntax1 ( )
{
// I don't know what this syntax means so cppcheck should bail out
check ( " void foo() \n "
" { \n "
" void *sym = ( { \n "
" void *__ptr = malloc(100); \n "
" if(!__ptr && 100 != 0) \n "
" { \n "
" exit(1); \n "
" } \n "
" __ptr; \n "
" } ); \n "
" free(sym); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-10-01 10:56:59 +02:00
void knownFunctions ( )
{
check ( " void foo() \n "
" { \n "
" int *p = new int[100]; \n "
" typeid(p); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2009-10-12 21:36:28 +02:00
void same_function_name ( )
{
check ( " void a(char *p) \n "
" { } \n "
" void b() \n "
" { \n "
" char *p = malloc(10); \n "
" abc.a(p); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-04-24 22:24:03 +02:00
void functionParameter ( )
{
check ( " void a(char *p) \n "
" { \n "
" p = malloc(100); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2010-09-03 07:18:01 +02:00
// Ticket #2014 - setjmp / longjmp
void jmp ( )
{
check ( " int main() \n "
" { \n "
" jmp_buf env; \n "
" int val; \n "
" char *a; \n "
" \n "
" val = setjmp(env); \n "
" if(val) \n "
" { \n "
" delete a; \n "
" return 0; \n "
" } \n "
" \n "
" a = new char(1); \n "
" longjmp(env, 1); \n "
" \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-09-27 12:25:34 +02:00
void trac1949 ( )
{
check ( " \n "
" \n "
" int fn() \n "
" { \n "
" char * buff = new char[100]; \n "
" assert (buff); \n "
" \n "
" \n "
" \n "
" return 0; \n "
" } \n "
) ;
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: buff \n " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
} ;
2009-06-08 20:20:43 +02:00
static TestMemleakInFunction testMemleakInFunction ;
class TestMemleakInClass : public TestFixture
{
public :
TestMemleakInClass ( ) : TestFixture ( " TestMemleakInClass " )
{ }
private :
2010-04-18 21:14:25 +02:00
/**
* Tokenize and execute leak check for given code
* @ param code Source code
2010-05-16 19:55:16 +02:00
* @ param inconclusive inconclusive checking
2010-04-18 21:14:25 +02:00
*/
2010-05-29 19:29:59 +02:00
void check ( const char code [ ] )
2009-06-08 20:20:43 +02:00
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
settings . _checkCodingStyle = true ;
2009-06-08 20:20:43 +02:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2009-06-08 20:20:43 +02:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . setVarId ( ) ;
tokenizer . simplifyTokenList ( ) ;
2010-12-01 18:00:55 +01:00
tokenizer . fillFunctionList ( ) ;
2009-06-08 20:20:43 +02:00
// Check for memory leaks..
CheckMemoryLeakInClass checkMemoryLeak ( & tokenizer , & settings , this ) ;
checkMemoryLeak . check ( ) ;
}
void run ( )
{
TEST_CASE ( class1 ) ;
TEST_CASE ( class2 ) ;
TEST_CASE ( class3 ) ;
TEST_CASE ( class4 ) ;
TEST_CASE ( class6 ) ;
TEST_CASE ( class7 ) ;
TEST_CASE ( class8 ) ;
TEST_CASE ( class9 ) ;
TEST_CASE ( class10 ) ;
TEST_CASE ( class11 ) ;
2009-10-22 21:51:58 +02:00
TEST_CASE ( class12 ) ;
2009-10-23 20:04:47 +02:00
TEST_CASE ( class13 ) ;
2010-01-27 22:05:04 +01:00
TEST_CASE ( class14 ) ;
2010-03-19 16:57:23 +01:00
TEST_CASE ( class15 ) ;
2010-06-12 13:37:44 +02:00
TEST_CASE ( class16 ) ;
2010-06-13 10:43:23 +02:00
TEST_CASE ( class17 ) ;
2010-06-16 19:28:47 +02:00
TEST_CASE ( class18 ) ;
2010-11-23 18:41:07 +01:00
TEST_CASE ( class19 ) ; // ticket #2219
2009-06-08 20:20:43 +02:00
2009-10-06 18:25:00 +02:00
TEST_CASE ( staticvar ) ;
2009-06-08 20:20:43 +02:00
TEST_CASE ( free_member_in_sub_func ) ;
2010-01-27 21:02:13 +01:00
TEST_CASE ( mismatch1 ) ;
2010-05-15 19:40:32 +02:00
// allocating member variable in public function
TEST_CASE ( func1 ) ;
TEST_CASE ( func2 ) ;
2009-06-08 20:20:43 +02:00
}
void class1 ( )
{
check ( " class Fred \n "
" { \n "
" private: \n "
" char *str1; \n "
" char *str2; \n "
" public: \n "
" Fred(); \n "
" ~Fred(); \n "
" }; \n "
" \n "
" Fred::Fred() \n "
" { \n "
" str1 = new char[10]; \n "
" str2 = new char[10]; \n "
" } \n "
" \n "
" Fred::~Fred() \n "
" { \n "
" delete [] str2; \n "
2010-05-29 19:29:59 +02:00
" } \n " ) ;
2010-06-13 19:00:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: Fred::str1 \n " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
2010-12-05 20:26:52 +01:00
check ( " class Fred \n "
" { \n "
" private: \n "
" char *str1; \n "
" char *str2; \n "
" public: \n "
" Fred() \n "
" { \n "
" str1 = new char[10]; \n "
" str2 = new char[10]; \n "
" } \n "
" ~Fred() \n "
" { \n "
" delete [] str2; \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: Fred::str1 \n " , errout . str ( ) ) ;
}
2009-06-08 20:20:43 +02:00
void class2 ( )
{
check ( " class Fred \n "
" { \n "
" private: \n "
" char *str1; \n "
" public: \n "
" Fred(); \n "
" ~Fred(); \n "
" }; \n "
" \n "
" Fred::Fred() \n "
" { \n "
" str1 = new char[10]; \n "
" } \n "
" \n "
" Fred::~Fred() \n "
" { \n "
" free(str1); \n "
2010-05-29 19:29:59 +02:00
" } \n " ) ;
2010-06-13 19:00:11 +02:00
ASSERT_EQUALS ( " [test.cpp:17]: (error) Mismatching allocation and deallocation: Fred::str1 \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class Fred \n "
" { \n "
" private: \n "
" char *str1; \n "
" public: \n "
" Fred() \n "
" { \n "
" str1 = new char[10]; \n "
" } \n "
" ~Fred() \n "
" { \n "
" free(str1); \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:12]: (error) Mismatching allocation and deallocation: Fred::str1 \n " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
void class3 ( )
{
check ( " class Token; \n "
" \n "
" class Tokenizer \n "
" { \n "
" private: \n "
" Token *_tokens; \n "
" \n "
" public: \n "
" Tokenizer(); \n "
" ~Tokenizer(); \n "
" void deleteTokens(Token *tok); \n "
" }; \n "
" \n "
" Tokenizer::Tokenizer() \n "
" { \n "
" _tokens = new Token; \n "
" } \n "
" \n "
" Tokenizer::~Tokenizer() \n "
" { \n "
" deleteTokens(_tokens); \n "
" } \n "
" \n "
" void Tokenizer::deleteTokens(Token *tok) \n "
" { \n "
" while (tok) \n "
" { \n "
" Token *next = tok->next(); \n "
" delete tok; \n "
" tok = next; \n "
" } \n "
2010-05-29 19:29:59 +02:00
" } \n " ) ;
2009-06-08 20:20:43 +02:00
2009-10-24 15:07:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class Token; \n "
" \n "
" class Tokenizer \n "
" { \n "
" private: \n "
" Token *_tokens; \n "
" \n "
" public: \n "
" Tokenizer() \n "
" { \n "
" _tokens = new Token; \n "
" } \n "
" ~Tokenizer() \n "
" { \n "
" deleteTokens(_tokens); \n "
" } \n "
" void deleteTokens(Token *tok) \n "
" { \n "
" while (tok) \n "
" { \n "
" Token *next = tok->next(); \n "
" delete tok; \n "
" tok = next; \n "
" } \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
void class4 ( )
{
check ( " struct ABC; \n "
" class Fred \n "
" { \n "
" private: \n "
" void addAbc(ABC *abc); \n "
" public: \n "
" void click(); \n "
" }; \n "
" \n "
" void Fred::addAbc(ABC* abc) \n "
" { \n "
" AbcPosts->Add(abc); \n "
" } \n "
" \n "
" void Fred::click() \n "
" { \n "
" ABC *p = new ABC; \n "
" addAbc( p ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " struct ABC; \n "
" class Fred \n "
" { \n "
" private: \n "
" void addAbc(ABC* abc) \n "
" { \n "
" AbcPosts->Add(abc); \n "
" } \n "
" public: \n "
" void click() \n "
" { \n "
" ABC *p = new ABC; \n "
" addAbc( p ); \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
void class6 ( )
{
check ( " class Fred \n "
" { \n "
" public: \n "
" void foo(); \n "
" }; \n "
" \n "
" void Fred::foo() \n "
" { \n "
" char *str = new char[100]; \n "
" delete [] str; \n "
" hello(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" void foo() \n "
" { \n "
" char *str = new char[100]; \n "
" delete [] str; \n "
" hello(); \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
void class7 ( )
{
check ( " class Fred \n "
" { \n "
" public: \n "
" int *i; \n "
" Fred(); \n "
" ~Fred(); \n "
" }; \n "
" \n "
" Fred::Fred() \n "
" { \n "
" this->i = new int; \n "
" } \n "
" Fred::~Fred() \n "
" { \n "
" delete this->i; \n "
2010-05-29 19:29:59 +02:00
" } \n " ) ;
2009-06-08 20:20:43 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" int *i; \n "
" Fred() \n "
" { \n "
" this->i = new int; \n "
" } \n "
" ~Fred() \n "
" { \n "
" delete this->i; \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
void class8 ( )
{
check ( " class A \n "
" { \n "
" public: \n "
" void a(); \n "
" void doNothing() { } \n "
" }; \n "
" \n "
" void A::a() \n "
" { \n "
" int* c = new int(1); \n "
" delete c; \n "
" doNothing(c); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" public: \n "
" void a() \n "
" { \n "
" int* c = new int(1); \n "
" delete c; \n "
" doNothing(c); \n "
" } \n "
" void doNothing() { } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
void class9 ( )
{
check ( " class A \n "
" { \n "
" public: \n "
" int * p; \n "
" A(); \n "
" ~A(); \n "
" }; \n "
" \n "
" A::A() \n "
" { p = new int; } \n "
" \n "
" A::~A() \n "
2010-05-29 19:29:59 +02:00
" { delete (p); } \n " ) ;
2009-06-08 20:20:43 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" public: \n "
" int * p; \n "
" A() \n "
" { p = new int; } \n "
" ~A() \n "
" { delete (p); } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
void class10 ( )
{
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" public: \n "
" int * p; \n "
" A(); \n "
" }; \n "
" A::A() \n "
" { p = new int; } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
check ( " class A \n "
" { \n "
" public: \n "
" int * p; \n "
" A() { p = new int; } \n "
2010-05-29 19:29:59 +02:00
" }; \n " ) ;
2010-06-13 19:00:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
void class11 ( )
{
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" public: \n "
" int * p; \n "
" A() : p(new int[10]) \n "
" { } "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
check ( " class A \n "
" { \n "
" public: \n "
" int * p; \n "
" A(); \n "
" }; \n "
" A::A() : p(new int[10]) \n "
2010-05-29 19:29:59 +02:00
" { } " ) ;
2010-06-13 19:00:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2009-10-22 21:51:58 +02:00
void class12 ( )
{
check ( " class A \n "
" { \n "
" private: \n "
" int *p; \n "
" public: \n "
" A(); \n "
" ~A(); \n "
" void cleanup(); "
" }; \n "
" \n "
" A::A() \n "
" { p = new int[10]; } \n "
" \n "
" A::~A() \n "
" { } \n "
" \n "
" void A::cleanup() \n "
2010-05-29 19:29:59 +02:00
" { delete [] p; } \n " ) ;
2010-06-13 19:00:11 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" private: \n "
" int *p; \n "
" public: \n "
" A() \n "
" { p = new int[10]; } \n "
" ~A() \n "
" { } \n "
" void cleanup() \n "
" { delete [] p; } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
2009-10-22 21:51:58 +02:00
}
2009-10-23 20:04:47 +02:00
void class13 ( )
{
check ( " class A \n "
" { \n "
" private: \n "
" int *p; \n "
" public: \n "
" A(); \n "
" ~A(); \n "
" void foo(); "
" }; \n "
" \n "
" A::A() \n "
" { } \n "
" \n "
" A::~A() \n "
" { } \n "
" \n "
" void A::foo() \n "
2010-05-29 19:29:59 +02:00
" { p = new int[10]; delete [] p; } \n " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " [test.cpp:17]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
check ( " class A \n "
" { \n "
" private: \n "
" int *p; \n "
" public: \n "
" A() \n "
" { } \n "
" ~A() \n "
" { } \n "
" void foo() \n "
" { p = new int[10]; delete [] p; } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:11]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
2009-10-23 20:04:47 +02:00
}
2010-01-27 22:05:04 +01:00
void class14 ( )
{
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init(); \n "
" }; \n "
" \n "
" void A::init() \n "
2010-05-29 19:29:59 +02:00
" { p = new int[10]; } \n " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n "
" [test.cpp:3]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init() \n "
" { p = new int[10]; } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n "
" [test.cpp:3]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
2010-06-11 13:33:10 +02:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init(); \n "
" }; \n "
" \n "
" void A::init() \n "
" { p = new int; } \n " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n "
" [test.cpp:3]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init() \n "
" { p = new int; } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n "
" [test.cpp:3]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
2010-06-11 13:33:10 +02:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init(); \n "
" }; \n "
" \n "
" void A::init() \n "
" { p = malloc(sizeof(int)*10); } \n " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n "
" [test.cpp:3]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init() \n "
" { p = malloc(sizeof(int)*10); } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n "
" [test.cpp:3]: (error) Memory leak: A::p \n " , errout . str ( ) ) ;
2010-01-27 22:05:04 +01:00
}
2010-03-19 16:57:23 +01:00
void class15 ( )
{
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" A(); \n "
" ~A() { delete [] p; } \n "
" }; \n "
" A::A() \n "
2010-05-29 19:29:59 +02:00
" { p = new int[10]; } " ) ;
2010-03-19 16:57:23 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-11 13:33:10 +02:00
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" A() \n "
" { p = new int[10]; } \n "
" ~A() { delete [] p; } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-11 13:33:10 +02:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" A(); \n "
" ~A() { delete p; } \n "
" }; \n "
" A::A() \n "
" { p = new int; } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" A() \n "
" { p = new int; } \n "
" ~A() { delete p; } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-11 13:33:10 +02:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" A(); \n "
" ~A() { free(p); } \n "
" }; \n "
" A::A() \n "
" { p = malloc(sizeof(int)*10); } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" A() \n "
" { p = malloc(sizeof(int)*10); } \n "
" ~A() { free(p); } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-03-19 16:57:23 +01:00
}
2010-06-12 13:37:44 +02:00
void class16 ( )
{
// Ticket #1510
check ( " class A \n "
" { \n "
" int *a; \n "
" int *b; \n "
" public: \n "
" A() { a = b = new int[10]; } \n "
" ~A() { delete [] a; } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-06-08 20:20:43 +02:00
2010-06-13 10:43:23 +02:00
void class17 ( )
{
// Ticket #1557
check ( " class A { \n "
" private: \n "
" char *pd; \n "
" public: \n "
" void foo(); \n "
" }; \n "
" \n "
" void A::foo() \n "
" { \n "
" A::pd = new char[12]; \n "
" delete [] A::pd; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:9]: (warning) Possible leak in public function. The pointer 'pd' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
check ( " class A { \n "
" private: \n "
" char *pd; \n "
" public: \n "
" void foo() \n "
" { \n "
" pd = new char[12]; \n "
" delete [] pd; \n "
" } \n "
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (warning) Possible leak in public function. The pointer 'pd' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
check ( " class A { \n "
" private: \n "
" char *pd; \n "
" public: \n "
" void foo(); \n "
" }; \n "
" \n "
" void A::foo() \n "
" { \n "
" pd = new char[12]; \n "
" delete [] pd; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:9]: (warning) Possible leak in public function. The pointer 'pd' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
2010-06-13 10:43:23 +02:00
}
2010-06-16 19:28:47 +02:00
void class18 ( )
{
// Ticket #853
check ( " class A : public x \n "
" { \n "
" public: \n "
" A() \n "
" { \n "
" a = new char[10]; \n "
" foo(a); \n "
" } \n "
" private: \n "
" char *a; \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A : public x \n "
" { \n "
" public: \n "
" A(); \n "
" private: \n "
" char *a; \n "
" }; \n "
" A::A() \n "
" { \n "
" a = new char[10]; \n "
" foo(a); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-16 19:28:47 +02:00
}
2010-11-23 18:41:07 +01:00
void class19 ( )
{
// Ticket #2219
check ( " class Foo \n "
" { \n "
" private: \n "
" TRadioButton* rp1; \n "
" TRadioButton* rp2; \n "
" public: \n "
" Foo(); \n "
" }; \n "
" Foo::Foo() \n "
" { \n "
" rp1 = new TRadioButton(this); \n "
" rp2 = new TRadioButton(this); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-04 07:29:12 +01:00
check ( " class TRadioButton { }; \n "
" class Foo \n "
" { \n "
" private: \n "
" TRadioButton* rp1; \n "
" TRadioButton* rp2; \n "
" public: \n "
" Foo(); \n "
" }; \n "
" Foo::Foo() \n "
" { \n "
" rp1 = new TRadioButton; \n "
" rp2 = new TRadioButton; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: Foo::rp1 \n "
" [test.cpp:6]: (error) Memory leak: Foo::rp2 \n " , errout . str ( ) ) ;
check ( " class TRadioButton { }; \n "
" class Foo \n "
" { \n "
" private: \n "
" TRadioButton* rp1; \n "
" TRadioButton* rp2; \n "
" public: \n "
" Foo(); \n "
" ~Foo(); \n "
" }; \n "
" Foo::Foo() \n "
" { \n "
" rp1 = new TRadioButton; \n "
" rp2 = new TRadioButton; \n "
" } \n "
" Foo::~Foo() \n "
" { \n "
" delete rp1; \n "
" delete rp2; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-23 18:41:07 +01:00
}
2009-10-06 18:25:00 +02:00
void staticvar ( )
{
check ( " class A \n "
" { \n "
" private: \n "
" static int * p; \n "
" public: "
" A() \n "
" { \n "
" if (!p) \n "
" p = new int[100]; \n "
" } \n "
2010-05-29 19:29:59 +02:00
" }; \n " ) ;
2009-10-06 18:25:00 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-06-08 20:20:43 +02:00
void free_member_in_sub_func ( )
{
2009-07-05 21:37:53 +02:00
// Member function
2009-06-08 20:20:43 +02:00
check ( " class Tokenizer \n "
" { \n "
" public: \n "
" Tokenizer(); \n "
" ~Tokenizer(); \n "
" \n "
" private: \n "
" int *_tokens; \n "
" static void deleteTokens(int *tok); \n "
" }; \n "
" \n "
" Tokenizer::Tokenizer() \n "
" { \n "
" _tokens = new int; \n "
" } \n "
" \n "
" Tokenizer::~Tokenizer() \n "
" { \n "
" deleteTokens(_tokens); \n "
" _tokens = 0; \n "
" } \n "
" \n "
" void Tokenizer::deleteTokens(int *tok) \n "
" { \n "
" delete tok; \n "
2010-05-29 19:29:59 +02:00
" } \n " ) ;
2009-10-24 15:07:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-05 21:37:53 +02:00
// Global function
check ( " void deleteTokens(int *tok) \n "
" { \n "
" delete tok; \n "
" } \n "
" class Tokenizer \n "
" { \n "
" public: \n "
" Tokenizer(); \n "
" ~Tokenizer(); \n "
" \n "
" private: \n "
" int *_tokens; \n "
" }; \n "
" \n "
" Tokenizer::Tokenizer() \n "
" { \n "
" _tokens = new int; \n "
" } \n "
" \n "
" Tokenizer::~Tokenizer() \n "
" { \n "
" deleteTokens(_tokens); \n "
" _tokens = 0; \n "
2010-05-29 19:29:59 +02:00
" } \n " ) ;
2009-10-24 15:07:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2010-01-27 21:02:13 +01:00
void mismatch1 ( )
{
check ( " class A \n "
" { \n "
" public: \n "
" A(int i); \n "
" ~A(); \n "
" private: \n "
" char* pkt_buffer; \n "
" }; \n "
" \n "
" A::A(int i) \n "
" { \n "
" pkt_buffer = new char[8192]; \n "
" if (i != 1) { \n "
" delete pkt_buffer; \n "
" pkt_buffer = 0; \n "
" } \n "
" } \n "
" \n "
" A::~A() { \n "
" delete [] pkt_buffer; \n "
2010-05-29 19:29:59 +02:00
" } \n " ) ;
2010-06-13 19:00:11 +02:00
ASSERT_EQUALS ( " [test.cpp:14]: (error) Mismatching allocation and deallocation: A::pkt_buffer \n " , errout . str ( ) ) ;
2010-01-27 21:02:13 +01:00
}
2010-05-15 19:40:32 +02:00
void func1 ( )
{
check ( " class Fred \n "
" { \n "
" private: \n "
" char *s; \n "
" public: \n "
" Fred() { s = 0; } \n "
" ~Fred() { free(s); } \n "
" void xy() \n "
" { s = malloc(100); } \n "
" }; \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
2010-01-27 21:02:13 +01:00
2010-05-15 19:40:32 +02:00
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred() { s = 0; } \n "
" ~Fred() { free(s); } \n "
" void xy() \n "
" { s = malloc(100); } \n "
" private: \n "
" char *s; \n "
" }; \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
TODO_ASSERT_EQUALS ( " publicAllocation " , errout . str ( ) ) ;
}
void func2 ( )
{
check ( " class Fred \n "
" { \n "
" private: \n "
" char *s; \n "
" public: \n "
" Fred() { s = 0; } \n "
" ~Fred() { free(s); } \n "
" const Fred & operator = (const Fred &f) \n "
" { s = malloc(100); } \n "
" }; \n " ) ;
2010-10-17 14:41:00 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
2010-05-15 19:40:32 +02:00
}
2009-06-08 20:20:43 +02:00
} ;
2008-12-18 22:28:57 +01:00
2009-06-08 20:20:43 +02:00
static TestMemleakInClass testMemleakInClass ;
2008-12-18 22:28:57 +01:00
2009-06-16 22:01:04 +02:00
class TestMemleakStructMember : public TestFixture
{
public :
TestMemleakStructMember ( ) : TestFixture ( " TestMemleakStructMember " )
{ }
private :
void check ( const char code [ ] )
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2009-06-16 22:01:04 +02:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2009-06-16 22:01:04 +02:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . simplifyTokenList ( ) ;
// Check for memory leaks..
CheckMemoryLeakStructMember checkMemoryLeakStructMember ( & tokenizer , & settings , this ) ;
checkMemoryLeakStructMember . check ( ) ;
}
void run ( )
{
2009-07-19 16:51:31 +02:00
// testing that errors are detected
TEST_CASE ( err ) ;
// handle / bail out when "goto" is found
TEST_CASE ( goto_ ) ;
// Don't report errors if the struct is returned
TEST_CASE ( ret ) ;
// assignments
TEST_CASE ( assign ) ;
// Failed allocation
TEST_CASE ( failedAllocation ) ;
2009-07-22 08:30:51 +02:00
// Deallocating in a function
TEST_CASE ( function ) ;
2009-07-23 22:29:31 +02:00
// Handle if-else
TEST_CASE ( ifelse ) ;
2009-09-28 22:58:06 +02:00
// struct variable is a global variable
TEST_CASE ( globalvar ) ;
2009-06-16 22:01:04 +02:00
}
2009-07-19 16:51:31 +02:00
void err ( )
2009-06-16 22:01:04 +02:00
{
check ( " static void foo() \n "
" { \n "
2009-07-19 16:51:31 +02:00
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" free(abc); \n "
2009-06-16 22:01:04 +02:00
" } \n " ) ;
2009-07-19 16:51:31 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: abc.a \n " , errout . str ( ) ) ;
check ( " static void foo() \n "
" { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: abc.a \n " , errout . str ( ) ) ;
check ( " static ABC * foo() \n "
" { \n "
" ABC *abc = malloc(sizeof(ABC)); \n "
" abc->a = malloc(10); \n "
" abc->b = malloc(10); \n "
" if (abc->b == 0) \n "
" { \n "
" return 0; \n "
" } \n "
" return abc; \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: abc.a \n " , errout . str ( ) ) ;
2009-07-20 14:39:24 +02:00
check ( " static void foo(int a) \n "
" { \n "
" ABC *abc = malloc(sizeof(ABC)); \n "
" abc->a = malloc(10); \n "
" if (a == 1) \n "
" { \n "
" free(abc->a); \n "
" return; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: abc.a \n " , errout . str ( ) ) ;
2009-07-19 16:51:31 +02:00
}
void goto_ ( )
{
check ( " static void foo() \n "
" { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" if (abc->a) \n "
" { goto out; } \n "
" free(abc); \n "
" return; \n "
" out: \n "
" free(abc->a); \n "
" free(abc); \n "
" } \n " ) ;
2009-09-28 22:41:45 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-19 16:51:31 +02:00
}
void ret ( )
{
check ( " static ABC * foo() \n "
" { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" return abc; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " static void foo(struct ABC *abc) \n "
" { \n "
" abc->a = malloc(10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void assign ( )
{
check ( " static void foo() \n "
" { \n "
" struct ABC *abc = abc1; \n "
" abc->a = malloc(10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " static void foo() \n "
" { \n "
" struct ABC *abc; \n "
" abc1 = abc = malloc(sizeof(ABC)); \n "
" abc->a = malloc(10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " static void foo() \n "
" { \n "
" struct msn_entry *ptr; \n "
" ptr = malloc(sizeof(struct msn_entry)); \n "
" ptr->msn = malloc(100); \n "
" back = ptr; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void failedAllocation ( )
{
check ( " static struct ABC * foo() \n "
" { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" if (!abc->a) \n "
" { \n "
" free(abc); \n "
" return 0; \n "
" } \n "
" return abc; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-16 22:01:04 +02:00
}
2009-07-22 08:30:51 +02:00
void function ( )
{
// Not found function => assume that the function may deallocate
check ( " static void foo() \n "
" { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" func(abc); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-29 11:38:20 +02:00
check ( " static void foo() \n "
" { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abclist.push_back(abc); \n "
" abc->a = malloc(10); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-22 08:30:51 +02:00
}
2009-07-23 22:29:31 +02:00
void ifelse ( )
{
check ( " static void foo() \n "
" { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" if (x) "
" { \n "
" abc->a = malloc(10); \n "
" } \n "
" else \n "
" { \n "
" free(abc); \n "
" return; \n "
" } \n "
" free(abc->a); \n "
" free(abc); \n "
" } \n " ) ;
2009-07-24 09:05:40 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-23 22:29:31 +02:00
}
2009-09-28 22:58:06 +02:00
void globalvar ( )
{
check ( " struct ABC *abc; \n "
" \n "
" static void foo() \n "
" { \n "
" abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" return; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-06-16 22:01:04 +02:00
} ;
static TestMemleakStructMember testMemleakStructMember ;
2010-11-12 21:09:34 +01:00
class TestMemleakNoVar : public TestFixture
{
public :
TestMemleakNoVar ( ) : TestFixture ( " TestMemleakNoVar " )
{ }
private :
void check ( const char code [ ] )
{
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings settings ;
2010-11-12 21:09:34 +01:00
// Tokenize..
2010-12-01 18:00:55 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2010-11-12 21:09:34 +01:00
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . simplifyTokenList ( ) ;
// Check for memory leaks..
CheckMemoryLeakNoVar checkMemoryLeakNoVar ( & tokenizer , & settings , this ) ;
checkMemoryLeakNoVar . check ( ) ;
}
void run ( )
{
// pass allocated memory to function..
TEST_CASE ( functionParameter ) ;
}
void functionParameter ( )
{
// standard function..
check ( " void x() { \n "
" strcpy(a, strdup(p)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Allocation with strdup, strcpy doesn't release it. \n " , errout . str ( ) ) ;
// user function..
check ( " void set_error(const char *msg) { \n "
" } \n "
" \n "
" void x() { \n "
" set_error(strdup(p)); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Allocation with strdup, set_error doesn't release it. \n " , errout . str ( ) ) ;
}
} ;
static TestMemleakNoVar testMemleakNoVar ;