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
2018-01-14 15:37:52 +01:00
* Copyright ( C ) 2007 - 2018 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 "checkmemoryleak.h"
2014-02-06 09:22:07 +01:00
# include "preprocessor.h"
2017-05-27 04:33:47 +02:00
# include "settings.h"
# include "simplecpp.h"
# include "standards.h"
# include "symboldatabase.h"
# include "testsuite.h"
# include "token.h"
# include "tokenize.h"
# include "tokenlist.h"
# include <list>
# include <ostream>
# include <string>
# include <vector>
struct InternalError ;
2008-12-18 22:28:57 +01:00
2009-06-15 17:44:59 +02:00
2011-10-13 20:53:06 +02:00
class TestMemleak : private TestFixture {
2009-06-15 17:44:59 +02:00
public :
2014-11-20 14:20:09 +01:00
TestMemleak ( ) : TestFixture ( " TestMemleak " ) {
2013-08-07 16:27:37 +02:00
}
2009-06-15 17:44:59 +02:00
private :
2015-10-07 18:33:57 +02:00
Settings settings ;
2018-05-15 16:37:40 +02:00
void run ( ) override {
2009-06-15 17:44:59 +02:00
TEST_CASE ( testFunctionReturnType ) ;
2010-01-26 20:10:52 +01:00
TEST_CASE ( open ) ;
2009-06-15 17:44:59 +02:00
}
2014-11-20 14:20:09 +01:00
CheckMemoryLeak : : AllocType functionReturnType ( const char code [ ] ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
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 " ) ;
2018-09-24 15:08:16 +02:00
const CheckMemoryLeak c ( & tokenizer , this , & settings ) ;
2013-06-29 12:55:24 +02:00
return c . functionReturnType ( & tokenizer . getSymbolDatabase ( ) - > scopeList . front ( ) . functionList . front ( ) ) ;
2009-06-15 17:44:59 +02:00
}
2014-11-20 14:20:09 +01:00
void testFunctionReturnType ( ) {
2009-06-15 17:44:59 +02:00
{
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
2014-11-20 14:20:09 +01:00
void open ( ) {
2010-01-26 20:10:52 +01:00
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 ( " " ) ;
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
2011-10-28 22:30:33 +02:00
const Token * tok = Token : : findsimplematch ( tokenizer . tokens ( ) , " ret = " ) ;
2018-09-24 15:08:16 +02:00
const CheckMemoryLeak check ( & tokenizer , 0 , & settings ) ;
2010-01-26 20:10:52 +01:00
ASSERT_EQUALS ( CheckMemoryLeak : : No , check . getAllocationType ( tok - > tokAt ( 2 ) , 1 ) ) ;
}
2009-06-15 17:44:59 +02:00
} ;
2015-10-07 14:30:01 +02:00
REGISTER_TEST ( TestMemleak )
2009-06-15 17:44:59 +02:00
2011-10-13 20:53:06 +02:00
class TestMemleakInFunction : public TestFixture {
2008-12-18 22:28:57 +01:00
public :
2014-11-20 14:20:09 +01:00
TestMemleakInFunction ( ) : TestFixture ( " TestMemleakInFunction " ) {
2013-08-07 16:27:37 +02:00
}
2008-12-18 22:28:57 +01:00
private :
2015-10-07 18:33:57 +02:00
Settings settings0 ;
2014-03-24 09:59:05 +01:00
Settings settings1 ;
2014-09-10 17:12:16 +02:00
Settings settings2 ;
2014-03-24 09:59:05 +01:00
2015-10-07 18:33:57 +02:00
void check ( const char code [ ] , bool c = false , bool posix = false , bool experimental = false , Settings * settings = nullptr ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2014-03-24 09:59:05 +01:00
if ( ! settings )
2013-05-23 06:34:22 +02:00
settings = & settings1 ;
2015-10-07 18:33:57 +02:00
settings - > experimental = experimental ;
settings - > standards . posix = posix ;
2010-12-01 18:00:55 +01:00
2008-12-18 22:28:57 +01:00
// Tokenize..
2013-05-23 06:34:22 +02:00
Tokenizer tokenizer ( settings , this ) ;
2008-12-18 22:28:57 +01:00
std : : istringstream istr ( code ) ;
2015-01-30 20:55:53 +01:00
tokenizer . tokenize ( istr , c ? " test.c " : " test.cpp " ) ;
2013-12-30 17:45:28 +01:00
tokenizer . simplifyTokenList2 ( ) ;
2008-12-18 22:28:57 +01:00
// Check for memory leaks..
2013-05-23 06:34:22 +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
2018-05-15 16:37:40 +02:00
void run ( ) override {
2014-09-01 13:54:33 +02:00
LOAD_LIB_2 ( settings1 . library , " std.cfg " ) ;
2015-11-19 17:33:52 +01:00
LOAD_LIB_2 ( settings1 . library , " posix.cfg " ) ;
2014-09-10 17:12:16 +02:00
LOAD_LIB_2 ( settings2 . library , " std.cfg " ) ;
2014-03-24 09:59:05 +01:00
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 ) ;
2015-04-09 20:50:19 +02:00
TEST_CASE ( nonstd_free ) ;
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 ) ;
2012-07-17 16:28:34 +02:00
TEST_CASE ( referencevar ) ; // 3954 - false positive for reference pointer
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 ) ;
2017-01-15 22:14:37 +01:00
TEST_CASE ( if12 ) ; // Ticket #7745
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 ) ;
2017-01-15 22:16:23 +01:00
TEST_CASE ( forwhile12 ) ;
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 ) ;
2011-05-19 19:41:18 +02:00
TEST_CASE ( mismatch5 ) ;
2013-05-23 06:34:22 +02:00
TEST_CASE ( mismatch6 ) ;
2009-01-05 16:49:57 +01:00
2010-12-16 21:27:33 +01:00
TEST_CASE ( mismatchSize ) ;
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;
2012-09-05 20:50:25 +02:00
TEST_CASE ( func20 ) ; // Ticket #2182 - exit is not handled
2011-03-22 00:59:53 +01:00
TEST_CASE ( func21 ) ; // Ticket #2569
TEST_CASE ( func22 ) ; // Ticket #2668
TEST_CASE ( func23 ) ; // Ticket #2667
2011-04-04 23:29:18 +02:00
TEST_CASE ( func24 ) ; // Ticket #2705
2011-07-15 01:15:59 +02:00
TEST_CASE ( func25 ) ; // Ticket #2904
2011-12-29 07:35:27 +01:00
TEST_CASE ( func26 ) ;
2012-07-02 10:01:37 +02:00
TEST_CASE ( func27 ) ; // Ticket #2773
2014-02-01 12:51:29 +01:00
TEST_CASE ( func28 ) ; // Ticket #3236
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 ) ;
2010-12-29 22:18:23 +01:00
TEST_CASE ( allocfunc7 ) ;
2011-03-19 14:05:22 +01:00
TEST_CASE ( allocfunc8 ) ;
2011-03-24 17:14:12 +01:00
TEST_CASE ( allocfunc9 ) ;
2011-07-24 16:08:29 +02:00
TEST_CASE ( allocfunc10 ) ;
2012-05-29 21:44:39 +02:00
TEST_CASE ( allocfunc11 ) ;
2012-06-25 20:00:50 +02:00
TEST_CASE ( allocfunc12 ) ; // #3660: allocating and returning non-local pointer => not allocfunc
2013-01-31 17:00:50 +01:00
TEST_CASE ( allocfunc13 ) ; // Ticket #4494 and #4540 - class function
2015-01-05 13:23:38 +01:00
TEST_CASE ( allocfunc14 ) ; // Use pointer before returning it
2009-06-15 17:44:59 +02:00
2016-05-26 17:42:27 +02:00
TEST_CASE ( inlineFunction ) ; // #3989 - inline function
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 ) ;
2014-11-07 07:44:12 +01:00
TEST_CASE ( linux_list_2 ) ;
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 ) ;
2011-01-13 07:33:46 +01:00
TEST_CASE ( realloc11 ) ;
2011-10-11 22:07:14 +02:00
TEST_CASE ( realloc12 ) ;
TEST_CASE ( realloc13 ) ;
TEST_CASE ( realloc14 ) ;
2011-11-25 07:23:54 +01:00
TEST_CASE ( realloc15 ) ;
2014-03-17 16:10:54 +01:00
TEST_CASE ( realloc16 ) ;
2008-12-18 22:28:57 +01:00
2011-05-29 17:44:10 +02:00
TEST_CASE ( assign1 ) ;
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 ) ;
2011-08-23 23:18:47 +02:00
TEST_CASE ( dealloc_use_2 ) ;
2011-08-31 05:42:11 +02:00
TEST_CASE ( dealloc_use_3 ) ;
2017-03-25 20:46:25 +01:00
TEST_CASE ( dealloc_use_4 ) ; // #7960
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 ) ;
2012-10-25 19:41:18 +02:00
TEST_CASE ( freefree3 ) ; // #4236 - FP. bar(&p)
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 ) ;
2011-03-07 20:17:52 +01:00
TEST_CASE ( class2 ) ;
2009-12-30 21:29:54 +01:00
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 ) ;
2017-01-14 12:16:47 +01:00
TEST_CASE ( conditional_dealloc_return ) ; // #7820
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 ) ;
2011-01-01 20:14:01 +01:00
TEST_CASE ( exit6 ) ;
TEST_CASE ( exit7 ) ;
2009-11-14 09:06:28 +01:00
TEST_CASE ( noreturn ) ;
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 ) ;
2018-10-01 11:58:27 +02:00
TEST_CASE ( fclose_comma ) ; // #7525
2009-06-21 17:01:43 +02:00
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 ) ;
2012-04-26 13:16:46 +02:00
TEST_CASE ( trac2540 ) ;
2011-03-20 09:16:52 +01:00
// #2662: segfault because of endless recursion (call_func -> getAllocationType -> functionReturnType -> call_func ..)
TEST_CASE ( trac2662 ) ;
2011-10-25 22:38:23 +02:00
// #1879 non regression test case
TEST_CASE ( trac1879 ) ;
2012-07-06 18:03:33 +02:00
2012-08-26 11:39:17 +02:00
TEST_CASE ( ptrptr ) ;
2014-01-27 16:51:18 +01:00
2015-01-30 20:55:53 +01:00
TEST_CASE ( c_code ) ;
2015-01-11 10:12:39 +01:00
TEST_CASE ( gnucfg ) ;
2015-07-25 18:50:27 +02:00
TEST_CASE ( trac3991 ) ;
2015-11-27 11:18:40 +01:00
TEST_CASE ( crash ) ;
2016-09-10 14:54:43 +02:00
TEST_CASE ( trac7680 ) ;
2017-01-27 22:53:24 +01:00
TEST_CASE ( trac7440 ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
std : : string getcode ( const char code [ ] , const char varname [ ] , bool classfunc = false ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2014-09-10 17:12:16 +02:00
settings2 . standards . posix = true ;
2010-12-01 18:00:55 +01:00
2009-08-23 11:26:17 +02:00
// Tokenize..
2014-09-10 17:12:16 +02:00
Tokenizer tokenizer ( & settings2 , this ) ;
2009-08-23 11:26:17 +02:00
std : : istringstream istr ( code ) ;
2012-08-12 12:01:24 +02:00
if ( ! tokenizer . tokenize ( istr , " test.cpp " ) )
return " " ;
2013-12-30 17:45:28 +01:00
tokenizer . simplifyTokenList2 ( ) ;
2017-01-06 11:53:17 +01:00
const Token * start = tokenizer . tokens ( ) ;
const SymbolDatabase * db = tokenizer . getSymbolDatabase ( ) ;
if ( db & & db - > functionScopes . size ( ) )
2018-04-27 22:36:30 +02:00
start = db - > functionScopes [ 0 ] - > bodyStart - > next ( ) ;
2009-06-14 19:32:34 +02:00
2017-01-06 11:53:17 +01:00
const unsigned int varId ( Token : : findmatch ( start , varname ) - > varId ( ) ) ;
2008-12-18 22:28:57 +01:00
2009-08-23 11:26:17 +02:00
// getcode..
2014-09-10 17:12:16 +02:00
CheckMemoryLeakInFunction checkMemoryLeak ( & tokenizer , & settings2 , nullptr ) ;
2018-04-09 09:41:24 +02:00
std : : list < const Token * > callstack ( 1 , nullptr ) ;
2009-08-23 11:26:17 +02:00
CheckMemoryLeak : : AllocType allocType , deallocType ;
allocType = deallocType = CheckMemoryLeak : : No ;
2017-01-06 11:53:17 +01:00
Token * tokens = checkMemoryLeak . getcode ( start , 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 ( ) ;
2012-05-05 18:33:26 +02:00
TokenList : : deleteTokens ( tokens ) ;
2009-08-23 11:26:17 +02:00
return ret . str ( ) ;
2008-12-18 22:28:57 +01:00
}
2009-08-30 21:11:15 +02:00
2014-11-20 14:20:09 +01:00
void testgetcode ( ) {
2009-08-23 11:26:17 +02:00
// alloc;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int *a = malloc(100); " , " a " ) ) ;
2014-10-01 10:59:08 +02:00
TODO_ASSERT_EQUALS ( " ;;alloc; " , " ;;alloccallfunc; " , getcode ( " int *a = ::malloc(100); " , " a " ) ) ;
2009-08-23 11:26:17 +02:00
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int *a = new int; " , " a " ) ) ;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int *a = new int[10]; " , " a " ) ) ;
2014-09-27 11:24:27 +02:00
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int **a = new int*[10]; " , " a " ) ) ;
2009-08-23 11:26:17 +02:00
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int * const a = new int[10]; " , " a " ) ) ;
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " const int * const a = new int[10]; " , " a " ) ) ;
2016-01-20 10:34:03 +01:00
ASSERT_EQUALS ( " ;;assign; " , getcode ( " A * a = new (X) A; " , " a " ) ) ;
2012-03-18 07:49:22 +01:00
ASSERT_EQUALS ( " ;;alloc; " , getcode ( " int i = open(a,b); " , " i " ) ) ;
ASSERT_EQUALS ( " ;;assign; " , getcode ( " int i = open(); " , " i " ) ) ;
2016-05-14 14:56:51 +02:00
ASSERT_EQUALS ( " ;;alloc;use; " , getcode ( " int *p; dostuff(p = new int); " , " p " ) ) ;
ASSERT_EQUALS ( " ;;alloc;use; " , getcode ( " int *p; dostuff(p = new int()); " , " p " ) ) ;
ASSERT_EQUALS ( " ;;alloc;use; " , getcode ( " int *p; fred.dostuff(p = new int); " , " p " ) ) ;
ASSERT_EQUALS ( " ;;alloc;use; " , getcode ( " int *p; fred.dostuff(p = new int()); " , " p " ) ) ;
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 " ) ) ;
2012-07-24 09:28:08 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; ::free(s); " , " s " ) ) ; // #2802
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 " ) ) ;
2011-01-30 12:54:19 +01:00
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 " ) ) ;
2012-07-27 12:25:20 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " char *s; s ? free(s) : 0; " , " s " ) ) ;
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 " ) ) ;
2014-11-20 22:19:39 +01:00
TODO_ASSERT_EQUALS ( " ;;ifv{} " , " ;;if{} " , getcode ( " char *s; if (a && s) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;ifv{} " , getcode ( " char *s; if (s && a) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;;ifv{} " , getcode ( " char *s; int a; if (a && s) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;;ifv{} " , getcode ( " char *s; int a; if (s && a) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;ifv{} " , getcode ( " char *s; if (a || s) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;ifv{} " , getcode ( " char *s; if (s || a) { } " , " s " ) ) ;
2009-08-23 11:26:17 +02:00
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 " ) ) ;
2010-12-17 21:34:22 +01:00
ASSERT_EQUALS ( " ;;use;if{} " , getcode ( " char *s; if (x(s)) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;use;if{} " , getcode ( " char *s; if (x(&s)) { } " , " s " ) ) ;
2010-12-22 18:32:00 +01:00
ASSERT_EQUALS ( " ;;use;if{} " , getcode ( " char *s; if (!s || x(&s)) { } " , " s " ) ) ;
2011-11-30 20:07:56 +01:00
ASSERT_EQUALS ( " ;;ifv{} " , getcode ( " int ffd; if (ffd<0 && (ffd=a)<0){} " , " ffd " ) ) ;
2009-09-04 19:11:19 +02:00
2011-01-10 19:35:06 +01:00
// if (ticket #2442)
ASSERT_EQUALS ( " ;;;;if(!var){;}ifv{} " , getcode ( " char *s; int x = 0; if (!s) { x = 2; } if (x) { } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;;;if(!var){;}if{} " , getcode ( " char *s; int x = 0; if (!s) { x = 2; } if (y) { } " , " s " ) ) ;
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 " ) ) ;
2012-03-18 07:49:22 +01:00
ASSERT_EQUALS ( " ;;alloc;while(var){} " , getcode ( " int fd = open(a,b); while (fd >= 0) { } " , " fd " ) ) ;
ASSERT_EQUALS ( " ;;alloc;while(!var){} " , getcode ( " int fd = open(a,b); 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 " ) ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " ;;alloc; " ,
" " , getcode ( " char *s; int ret; ret=asprintf(&s, \" xyz \" ); if (ret==-1) return; " , " s " ) ) ;
2009-08-29 07:26:32 +02:00
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 " ) ) ;
2012-12-09 08:59:21 +01:00
ASSERT_EQUALS ( " ;;useuse_; " , getcode ( " struct AB *ab; f(ab->a); " , " ab " ) ) ;
2011-08-28 11:28:14 +02:00
ASSERT_EQUALS ( " ;;use; " , getcode ( " struct AB *ab; ab = pop(ab); " , " ab " ) ) ;
2009-08-23 11:26:17 +02:00
2010-11-20 08:35:23 +01:00
// non-use..
2012-12-09 08:59:21 +01:00
ASSERT_EQUALS ( " ;;use_; " , getcode ( " char *s; c = x + s[0]; " , " s " ) ) ;
ASSERT_EQUALS ( " ;;use_; " , getcode ( " char *s; c = s[0] + x; " , " s " ) ) ;
ASSERT_EQUALS ( " ;;use_; " , getcode ( " type *c; y = x + c->y; " , " c " ) ) ;
ASSERT_EQUALS ( " ;;use_; " , getcode ( " type *c; y = c->y + x; " , " c " ) ) ;
ASSERT_EQUALS ( " ;;use_; " , getcode ( " char *s; s = s + 1; " , " s " ) ) ;
2014-04-06 18:45:24 +02:00
ASSERT_EQUALS ( " ;;dealloc;; " , getcode ( " struct foo *s; free(s); printf(a,sizeof(*s)); " , " s " ) ) ;
ASSERT_EQUALS ( " ;;do{dealloc;;}while(var); " , getcode ( " struct foo *s; do{free(s); printf(a,sizeof(*s));}while(s); " , " s " ) ) ;
2012-12-09 08:59:21 +01:00
// use reference
ASSERT_EQUALS ( " ;;callfunc&use; " , getcode ( " struct AB *ab; f(&ab); " , " ab " ) ) ;
2010-11-20 08:35:23 +01:00
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..
2011-01-01 20:14:01 +01:00
ASSERT_EQUALS ( " ;;assign; " , 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 " ) ) ;
2011-01-01 20:14:01 +01:00
ASSERT_EQUALS ( " ;;; " , getcode ( " char *s; x = a(); " , " s " ) ) ; // the function call is irrelevant
2009-08-23 11:26:17 +02:00
// exit..
ASSERT_EQUALS ( " ;;exit; " , getcode ( " char *s; exit(0); " , " s " ) ) ;
2015-11-19 18:51:32 +01:00
ASSERT_EQUALS ( " ;;callfunc; " , getcode ( " char *s; _exit(0); " , " s " ) ) ; // not in std.cfg
2009-09-12 14:11:17 +02:00
ASSERT_EQUALS ( " ;;exit; " , getcode ( " char *s; abort(); " , " s " ) ) ;
2015-11-19 18:51:32 +01:00
ASSERT_EQUALS ( " ;;callfunc; " , getcode ( " char *s; err(0); " , " s " ) ) ; // not in std.cfg
2009-08-25 22:18:22 +02:00
ASSERT_EQUALS ( " ;;if{exit;} " , getcode ( " char *s; if (a) { exit(0); } " , " s " ) ) ;
2017-02-25 12:12:39 +01:00
ASSERT_EQUALS ( " ;;if{exit;} " , getcode ( " char *s; if (a) { ::exit(0); } " , " s " ) ) ;
ASSERT_EQUALS ( " ;;if{exit;} " , getcode ( " char *s; if (a) { std::exit(0); } " , " s " ) ) ;
2009-08-29 07:43:44 +02:00
2009-11-15 10:30:00 +01:00
// list_for_each
2017-01-06 11:53:17 +01:00
ASSERT_EQUALS ( " ;;exit;{}} " , getcode ( " void f() { char *s; list_for_each(x,y,s) { } } " , " s " ) ) ;
2009-11-15 10:30:00 +01:00
2009-08-29 07:43:44 +02:00
// open/close
2012-03-18 07:49:22 +01:00
ASSERT_EQUALS ( " ;;alloc;if(var){dealloc;} " , getcode ( " int f; f=open(a,b); if(f>=0)close(f); " , " f " ) ) ;
2012-03-18 11:54:09 +01:00
ASSERT_EQUALS ( " ;;alloc;if(var){dealloc;} " , getcode ( " int f; f=open(a,b); if(f>-1)close(f); " , " f " ) ) ;
2012-03-18 07:49:22 +01:00
ASSERT_EQUALS ( " ;;alloc;ifv{;} " , getcode ( " int f; f=open(a,b); if(f!=-1 || x); " , " f " ) ) ;
2012-08-10 18:31:22 +02:00
ASSERT_EQUALS ( " ;;;dealloc;loop{} " , getcode ( " ;int f; while (close(f) == -1) { } " , " f " ) ) ;
ASSERT_EQUALS ( " ;;;dealloc;assign;; " , getcode ( " ;int res; res = close(res); " , " res " ) ) ;
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 " ) ) ;
2014-09-30 13:19:53 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " int f; e += fclose(f); " , " f " ) ) ;
2014-09-30 13:55:21 +02:00
ASSERT_EQUALS ( " ;;dealloc; " , getcode ( " int f; foo(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
2014-03-27 13:15:21 +01:00
ASSERT_THROW ( getcode ( " page *one = foo(); \n "
" ASSERT(one, return 0) \n "
" const int two = rand(); \n "
" return 0; \n "
" } " , " one " ) , InternalError ) ;
2010-12-21 21:12:45 +01:00
// ticket #2336: calling member function with same name as a white_list function
ASSERT_EQUALS ( " ;;use; " , getcode ( " char *s; foo.write(s); " , " s " ) ) ;
2011-01-17 19:00:21 +01:00
// #2473 - inner struct
ASSERT_EQUALS ( " ;;alloc;{;;};dealloc; " ,
getcode ( " char *s = new char[10]; \n "
" struct ab { int a, b; }; \n "
" delete [] s; \n " , " s " ) ) ;
2012-12-16 18:06:40 +01:00
// #4405 - catch
ASSERT_EQUALS ( " ;;catch{} " , getcode ( " char *s; catch(err) { } " , " s " ) ) ;
2009-08-25 22:18:22 +02:00
}
2015-01-30 20:55:53 +01:00
bool test_white_list ( const std : : string & str , bool cpp = true ) const {
return CheckMemoryLeakInFunction : : test_white_list ( str , & settings1 , cpp ) ;
}
2009-08-25 22:18:22 +02:00
2014-11-20 14:20:09 +01:00
void call_func ( ) const {
2010-01-18 21:34:11 +01:00
// whitelist..
2015-01-30 20:55:53 +01:00
ASSERT_EQUALS ( true , test_white_list ( " qsort " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " scanf " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " sscanf " ) ) ;
2010-01-18 21:34:11 +01:00
2010-01-20 22:03:06 +01:00
// #1293
2015-01-30 20:55:53 +01:00
ASSERT_EQUALS ( true , test_white_list ( " time " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " asctime " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " asctime_r " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " ctime " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " ctime_r " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " gmtime " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " gmtime_r " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " localtime " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " localtime_r " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " memcmp " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " gets " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " vprintf " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " vfprintf " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " vsprintf " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " snprintf " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " vsnprintf " ) ) ;
ASSERT_EQUALS ( true , test_white_list ( " delete " , true ) ) ;
ASSERT_EQUALS ( false , test_white_list ( " delete " , false ) ) ;
2010-01-20 22:03:06 +01:00
2011-10-13 20:53:06 +02:00
static const char * const call_func_white_list [ ] = {
2015-01-30 20:55:53 +01:00
" access " , " asprintf " , " atof " , " atoi " , " atol " , " chdir " , " chmod " , " clearerr " , " chown "
2011-03-21 00:07:37 +01:00
, " fchmod " , " fcntl " , " fdatasync " , " feof " , " ferror " , " fflush " , " fgetc " , " fgetpos " , " fgets "
2011-03-21 15:12:21 +01:00
, " flock " , " for " , " fprintf " , " fputc " , " fputs " , " fread " , " free " , " freopen " , " fscanf " , " fseek "
2010-01-18 21:34:11 +01:00
, " fseeko " , " fsetpos " , " fstat " , " fsync " , " ftell " , " ftello " , " ftruncate "
2011-03-21 23:20:46 +01:00
, " fwrite " , " getc " , " if " , " ioctl " , " lockf " , " lseek " , " open " , " memchr " , " memcpy "
2011-11-07 22:50:57 +01:00
, " memmove " , " memset " , " mkstemp " , " perror " , " posix_fadvise " , " posix_fallocate " , " pread "
2010-01-18 21:34:11 +01:00
, " printf " , " puts " , " pwrite " , " read " , " readahead " , " readdir " , " readdir_r " , " readv "
, " realloc " , " return " , " rewind " , " rewinddir " , " scandir " , " seekdir "
2011-03-21 23:59:43 +01:00
, " setbuf " , " setbuffer " , " setlinebuf " , " setvbuf " , " snprintf " , " sprintf " , " stpcpy " , " strcasecmp "
2010-01-18 21:34:11 +01:00
, " strcat " , " strchr " , " strcmp " , " strcpy " , " stricmp " , " strlen " , " strncat " , " strncmp "
2018-01-08 20:20:33 +01:00
, " strncpy " , " strrchr " , " strspn " , " strstr " , " strtod " , " strtol " , " strtoul " , " switch "
2011-03-20 22:17:51 +01:00
, " sync_file_range " , " telldir " , " typeid " , " while " , " write " , " writev " , " lstat " , " stat "
2011-03-21 23:59:43 +01:00
, " _open " , " _wopen " , " vscanf " , " vsscanf " , " vfscanf " , " vasprintf " , " utime " , " utimes " , " unlink "
, " tempnam " , " system " , " symlink " , " strpbrk " , " strncasecmp " , " strdup " , " strcspn " , " strcoll "
2011-03-22 22:13:29 +01:00
, " setlocale " , " sethostname " , " rmdir " , " rindex " , " rename " , " remove " , " adjtime " , " creat " , " execle "
2011-06-20 18:42:13 +02:00
, " execl " , " execlp " , " execve " , " execv " , " fmemopen " , " fnmatch " , " fopencookie " , " fopen "
2011-03-22 22:13:29 +01:00
, " getgrnam " , " gethostbyaddr " , " getnetbyname " , " getopt " , " getopt_long " , " getprotobyname " , " getpwnam "
, " getservbyname " , " getservbyport " , " glob " , " index " , " inet_addr " , " inet_aton " , " inet_network "
, " initgroups " , " link " , " mblen " , " mbstowcs " , " mbtowc " , " mkdir " , " mkfifo " , " mknod " , " obstack_printf "
2011-12-29 07:35:27 +01:00
, " obstack_vprintf " , " opendir " , " parse_printf_format " , " pathconf " , " popen " , " psignal "
2011-09-09 07:25:47 +02:00
, " readlink " , " regcomp " , " strxfrm " , " wordexp " , " sizeof " , " strtok "
2010-01-18 21:34:11 +01:00
} ;
2011-10-13 20:53:06 +02:00
for ( unsigned int i = 0 ; i < ( sizeof ( call_func_white_list ) / sizeof ( char * ) ) ; + + i ) {
2015-01-30 20:55:53 +01:00
bool ret = test_white_list ( call_func_white_list [ i ] ) ;
2011-09-09 07:25:47 +02:00
ASSERT_EQUALS ( " " , ret ? " " : call_func_white_list [ i ] ) ;
}
2010-01-18 21:34:11 +01:00
}
2009-08-25 22:18:22 +02:00
2014-11-20 14:20:09 +01:00
std : : string simplifycode ( const char code [ ] ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2009-08-25 22:18:22 +02:00
// Tokenize..
std : : istringstream istr ( code ) ;
2015-10-07 18:33:57 +02:00
Tokenizer tokenizer ( & settings0 , this ) ;
tokenizer . list . createTokens ( istr , " test.cpp " ) ;
2009-08-25 22:18:22 +02:00
// replace "if ( ! var )" => "if(!var)"
2015-10-07 18:33:57 +02:00
for ( Token * tok = tokenizer . list . front ( ) ; tok ; tok = tok - > next ( ) ) {
2011-10-13 20:53:06 +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
}
2011-10-13 20:53:06 +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
}
2015-10-07 18:33:57 +02:00
CheckMemoryLeakInFunction checkMemoryLeak ( & tokenizer , & settings0 , this ) ;
checkMemoryLeak . simplifycode ( tokenizer . list . front ( ) ) ;
2009-08-25 22:18:22 +02:00
2015-10-07 18:33:57 +02:00
return tokenizer . tokens ( ) - > stringifyList ( 0 , false ) ;
2008-12-18 22:28:57 +01:00
}
2009-08-25 22:18:22 +02:00
// Test that the CheckMemoryLeaksInFunction::simplifycode works
2014-11-20 14:20:09 +01:00
void simplifycode ( ) {
2009-08-25 22:18:22 +02:00
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 ; } " ) ) ;
2012-12-09 08:59:21 +01:00
ASSERT_EQUALS ( " ; use ; } " , simplifycode ( " ; use use_ ; } " ) ) ;
ASSERT_EQUALS ( " ; use ; } " , simplifycode ( " ; use_ use ; } " ) ) ;
ASSERT_EQUALS ( " ; use ; } " , simplifycode ( " ; &use use ; } " ) ) ;
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 ; " ) ) ;
2013-01-27 02:41:43 +01:00
ASSERT_EQUALS ( " ; break ; " , 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 ; } " ) ) ;
2013-01-27 02:41:43 +01:00
ASSERT_EQUALS ( " ; alloc ; if 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
2011-04-20 06:41:14 +02:00
// remove outer if (#2733)
ASSERT_EQUALS ( " alloc ; return ; } " , simplifycode ( " alloc ; if { if return use ; } return ; } " ) ) ;
ASSERT_EQUALS ( " alloc ; return ; } " , simplifycode ( " alloc ; if { if(var) return use ; } return ; } " ) ) ;
2011-04-20 17:16:09 +02:00
ASSERT_EQUALS ( " alloc ; return ; } " , simplifycode ( " alloc ; if(var) { if return use ; } return ; } " ) ) ;
2011-04-20 06:41:14 +02: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 ; } ; } " ) ) ;
2011-12-03 09:53:36 +01:00
{
// ticket #3267
const char expected [ ] = " ; loop if alloc ; if { dealloc ; return ; } } " ;
ASSERT_EQUALS ( expected , simplifycode ( " ; loop { if alloc ; } if { dealloc ; return ; } } " ) ) ;
ASSERT_EQUALS ( expected , simplifycode ( " ; loop { if { alloc ; if(!var) { return ; } } } if { dealloc ; return ; } } " ) ) ;
}
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-12-09 06:13:33 +01:00
ASSERT_EQUALS ( " ; use ; " , simplifycode ( " ; while1 { if { dealloc ; return ; } if { if { continue ; } } } " ) ) ;
2010-12-08 21:02:02 +01:00
2010-04-27 20:43:31 +02:00
// scope..
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " ; assign ; if alloc ; } " ,
" ; assign ; dealloc ; if alloc ; } " , simplifycode ( " ; assign ; { dealloc ; if alloc ; } } " ) ) ;
2010-04-27 20:43:31 +02:00
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 ; } " ) ) ;
2012-12-16 18:06:40 +01:00
ASSERT_EQUALS ( " alloc ; dealloc ; } " , simplifycode ( " alloc ; if { dealloc ; callfunc } dealloc ; } " ) ) ; // #4405
2009-08-30 21:11:15 +02:00
2011-08-02 09:04:13 +02:00
// #2900 - don't report false positive
ASSERT_EQUALS ( " ; alloc ; if { if { dealloc ; callfunc ; } return ; } dealloc ; } " ,
simplifycode ( " ; alloc ; if { if { dealloc ; callfunc ; } return ; } dealloc ; } " ) ) ;
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; } " ) ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " ; " ,
" ; if(var) exit ; " , simplifycode ( " ; alloc ; if(var) { exit; } " ) ) ;
TODO_ASSERT_EQUALS ( " ; \n ; alloc ; " ,
" ; alloc ; ifv exit ; " , 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 ; " ) ) ;
2011-03-09 19:53:59 +01:00
// #2635 - false negative
ASSERT_EQUALS ( " ; alloc ; return use ; } " ,
simplifycode ( " ; alloc ; if(!var) { loop { ifv { } } alloc ; } return use; } " ) ) ;
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
2015-10-07 18:33:57 +02:00
unsigned int dofindleak ( const char code [ ] ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2018-08-05 14:01:24 +02:00
settings0 . debugwarnings = true ;
2010-12-01 18:00:55 +01:00
// Tokenize..
2009-08-23 15:48:25 +02:00
std : : istringstream istr ( code ) ;
2015-10-07 18:33:57 +02:00
TokenList list ( & settings0 ) ;
2013-01-27 02:41:43 +01:00
list . createTokens ( istr , " test.cpp " ) ;
Token * tokens = list . front ( ) ;
2009-08-23 15:48:25 +02:00
// replace "if ( ! var )" => "if(!var)"
2013-01-27 02:41:43 +01:00
for ( Token * tok = tokens ; tok ; tok = tok - > next ( ) ) {
2011-10-13 20:53:06 +02:00
if ( tok - > str ( ) = = " if_var " ) {
2009-10-27 23:08:11 +01:00
tok - > str ( " if(var) " ) ;
}
2011-10-13 20:53:06 +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) " ) ;
}
2011-10-13 20:53:06 +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) " ) ;
}
}
2013-01-27 02:41:43 +01:00
const Token * tok = CheckMemoryLeakInFunction : : findleak ( tokens ) ;
2015-10-07 18:33:57 +02:00
2018-08-05 14:01:24 +02:00
settings0 . debugwarnings = false ;
2015-10-07 18:33:57 +02:00
2009-12-26 17:49:05 +01:00
return ( tok ? tok - > linenr ( ) : ( unsigned int ) ( - 1 ) ) ;
2009-08-23 15:48:25 +02:00
}
2015-10-07 18:33:57 +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..
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( 1 , notfound , dofindleak ( " ; loop { alloc ; if break; dealloc ; } " ) ) ;
TODO_ASSERT_EQUALS ( 1 , notfound , 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
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void simple7 ( ) {
2011-10-13 20:55:55 +02:00
// A garbage collector may delete f automatically
2009-01-05 16:49:57 +01:00
check ( " class Fred; \n "
" void foo() \n "
" { \n "
" Fred *f = new Fred; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void simple11 ( ) {
2009-06-17 21:42:49 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-17 21:42:49 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-04-09 20:50:19 +02:00
void nonstd_free ( ) {
check ( " void f() { \n "
" void* mem = malloc(100, foo); " // Non-standard malloc() implementation
" free(mem, bar); " // Non-standard free() implementation (#5665)
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-06-17 21:42:49 +02:00
2014-11-20 14:20:09 +01:00
void new_nothrow ( ) {
2009-06-05 06:03:48 +02:00
check ( " void f() \n "
" { \n "
" int *p = new(std::nothrow) int; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-06-05 06:03:48 +02:00
check ( " void f() \n "
" { \n "
" using std::nothrow; \n "
" int *p = new(nothrow) int; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-06-05 06:03:48 +02:00
check ( " void f() \n "
" { \n "
" int *p = new(std::nothrow) int; \n "
" delete [] p; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 06:03:48 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 06:03:48 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-07-05 14:01:25 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" Fred *f = new(std::nothrow) Fred; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-07-05 14:01:25 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-07 01:10:15 +02:00
// ticket #2971
check ( " void f() \n "
" { \n "
" Fred *f = new(std::nothrow) Fred[10]; \n "
" delete f; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-08-07 01:10:15 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Mismatching allocation and deallocation: f \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" struct Fred *f = new(std::nothrow) struct Fred[10]; \n "
" delete f; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-08-07 01:10:15 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Mismatching allocation and deallocation: f \n " , 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
2014-11-20 14:20:09 +01:00
void staticvar ( ) {
2009-07-06 12:20:13 +02:00
check ( " int f() \n "
" { \n "
" static char *s = 0; \n "
" free(s); \n "
" s = malloc(100); \n "
" return 123; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-06 12:20:13 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void externvar ( ) {
2009-10-04 14:24:41 +02:00
check ( " void f() \n "
" { \n "
" extern char *s; \n "
" s = malloc(100); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-10-04 14:24:41 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void referencevar ( ) { // 3954 - false positive for reference pointer
2012-07-17 16:28:34 +02:00
check ( " void f() { \n "
" char *&x = get(); \n "
" x = malloc(100); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-07-17 16:28:34 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-07-06 12:20:13 +02:00
2014-11-20 14:20:09 +01:00
void alloc_alloc_1 ( ) {
2009-02-07 10:44:57 +01:00
check ( " void foo() \n "
" { \n "
" char *str; \n "
" str = new char[10]; \n "
" str = new char[20]; \n "
" delete [] str; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: str \n " , errout . str ( ) ) ;
2009-02-07 10:44:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: s \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void ifelse10 ( ) {
2009-02-25 20:20:23 +01:00
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 "
2015-10-07 18:33:57 +02:00
" } \n " , false , false , 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
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: c \n " , errout . str ( ) ) ;
2008-12-22 15:42:54 +01:00
}
2014-11-20 14:20:09 +01:00
void if9 ( ) {
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-08 14:35:09 +01: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
}
2014-11-20 14:20:09 +01:00
void if11 ( ) {
2009-02-04 07:11:36 +01:00
check ( " void foo() \n "
" { \n "
" int *x = new int[10]; \n "
" if (x == 0 || aa) \n "
" { \n "
" return 1; \n "
" } \n "
" delete [] x; \n "
2015-10-07 18:33:57 +02:00
" } " , false , false , true ) ;
2011-11-30 19:43:02 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:6]: (error) Memory leak: x \n " ,
2011-01-30 12:54:19 +01:00
" " , errout . str ( ) ) ;
2009-02-04 07:11:36 +01:00
}
2008-12-18 22:28:57 +01:00
2017-01-15 22:14:37 +01:00
void if12 ( ) { // #7745
check ( " void f() { \n "
" FILE *fp = fopen( \" name \" , \" r \" ); \n "
" if (!fp) { \n "
" fp = fopen( \" name \" , \" w \" ); \n "
" fclose(fp); \n "
" } \n "
" } " , /*c=*/ true , /*posix=*/ false ) ;
ASSERT_EQUALS ( " [test.c:7]: (error) Resource leak: fp \n " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: str \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void forwhile8 ( ) {
2008-12-18 22:28:57 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: a \n " ,
2011-01-30 12:54:19 +01:00
" [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
}
2014-11-20 14:20:09 +01:00
void forwhile9 ( ) {
2009-01-10 17:28:04 +01:00
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 "
2015-10-07 18:33:57 +02:00
" } \n " , false , false , true ) ;
2011-01-08 14:35:09 +01: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
}
2014-11-20 14:20:09 +01:00
void forwhile10 ( ) {
2009-01-10 17:28:04 +01:00
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 "
2015-10-07 18:33:57 +02:00
" } " , false , false , true ) ;
2011-01-08 14:35:09 +01:00
ASSERT_EQUALS ( " [test.cpp:9]: (error) Common realloc mistake: \' a \' nulled but not freed upon failure \n "
2011-11-30 19:43:02 +01:00
" [test.cpp:11]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2009-01-10 17:28:04 +01:00
}
2014-11-20 14:20:09 +01:00
void forwhile11 ( ) {
2009-06-20 13:58:30 +02:00
check ( " int main() \n "
" { \n "
" FILE *stream=NULL; \n "
" while((stream = fopen(name, \" r \" )) == NULL) \n "
" { } \n "
" if(stream!=NULL) fclose(stream); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-20 13:58:30 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2017-01-15 22:16:23 +01:00
void forwhile12 ( ) {
check ( " extern int bar(); \n "
" void f() { \n "
" FILE *fp = fopen( \" name \" , \" r \" ); \n "
" while(bar()) { \n "
" fp = fopen( \" name \" , \" w \" ); \n "
" fclose(fp); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Resource leak: fp \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" FILE *fp = fopen( \" name \" , \" r \" ); \n "
" while(1) { \n "
" fp = fopen( \" name \" , \" w \" ); \n "
" fclose(fp); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: fp \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
2017-01-15 22:16:23 +01:00
check ( " void f() { \n "
" FILE *fp = fopen( \" name \" , \" r \" ); \n "
" for( ; ; ) { \n "
" fp = fopen( \" name \" , \" w \" ); \n "
" fclose(fp); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: fp \n " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +01:00
void switch2 ( ) {
2014-04-02 13:56:34 +02:00
check ( " 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 "
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:12]: (error) Memory leak: str \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void switch3 ( ) {
2009-01-17 08:55:40 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +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
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-25 09:27:07 +01:00
}
2014-11-20 14:20:09 +01:00
void ret6 ( ) {
2009-02-24 07:23:21 +01:00
check ( " void foo() \n "
" { \n "
" char *c = new char[50]; \n "
" return strcpy(c, \" foo \" ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-24 07:23:21 +01:00
}
2014-11-20 14:20:09 +01:00
void ret7 ( ) {
2009-03-03 21:39:17 +01:00
check ( " void foo() \n "
" { \n "
" char *c = new char[50]; \n "
" return memcpy(c, \" foo \" ,4); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
2014-11-20 14:20:09 +01:00
void ret8 ( ) {
2009-06-05 08:56:46 +02:00
check ( " char *foo() \n "
" { \n "
" char *c = new char[50]; \n "
" return ((char *)(c+1)); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 08:56:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-25 09:27:07 +01:00
2014-11-20 14:20:09 +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 "
2015-10-07 18:33:57 +02:00
" } \n " , false , false , true ) ;
2009-05-31 21:48:55 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Mismatching allocation and deallocation: a \n " , errout . str ( ) ) ;
2011-08-07 01:10:15 +02:00
// ticket #2971
check ( " void f() \n "
" { \n "
" Fred *a = new Fred[10]; \n "
" free(a); \n "
2015-10-07 18:33:57 +02:00
" } \n " , false , false , true ) ;
2011-08-07 01:10:15 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Mismatching allocation and deallocation: a \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" struct Fred *a = new struct Fred[10]; \n "
" free(a); \n "
2015-10-07 18:33:57 +02:00
" } \n " , false , false , true ) ;
2011-08-07 01:10:15 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Mismatching allocation and deallocation: a \n " , errout . str ( ) ) ;
2015-11-27 11:04:18 +01:00
check ( " void f() { \n "
" char* str = new char[42](); \n "
" delete[] str; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void mismatch2 ( ) {
2009-01-31 12:51:47 +01:00
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 "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
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
2014-11-20 14:20:09 +01:00
void mismatch3 ( ) {
2009-02-02 06:58:50 +01:00
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 "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-02 06:58:50 +01:00
}
2014-11-20 14:20:09 +01:00
void mismatch4 ( ) {
2009-02-02 06:58:50 +01:00
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 "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
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
}
2014-11-20 14:20:09 +01:00
void mismatch5 ( ) {
2011-05-19 19:41:18 +02:00
check ( " void f() { \n "
" C *c = new C; \n "
" delete c; \n "
" c = new C[2]; \n "
" delete [] c; \n "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void mismatch6 ( ) { // #4599
2013-05-23 06:34:22 +02:00
check ( " void test ( int do_gzip , const char * fn ) { \n "
" FILE * f ; \n "
" if ( do_gzip ) { \n "
" f = popen ( fn , \" wb \" ) ; \n "
" } else { \n "
" f = fopen ( fn , \" wb \" ) ; \n "
" } \n "
" if ( do_gzip ) { \n "
" pclose ( f ) ; } \n "
" else { \n "
" fclose ( f ) ; } \n "
" } " ) ;
2011-05-19 19:41:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void mismatchSize ( ) {
2010-12-16 21:27:33 +01:00
check ( " void f(char *buf) \n "
" { \n "
" int i; \n "
" buf = malloc(3); \n "
" buf[i] = 0; \n "
" free(buf); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-12-16 21:27:33 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
////////////////////////////////////////////////
// function calls
////////////////////////////////////////////////
2014-11-20 14:20:09 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2015-10-07 18:33:57 +02:00
" } " , false , false , 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
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: p \n " ,
2011-01-30 12:54:19 +01:00
" " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-25 08:50:25 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-02 01:05:08 +01:00
}
2014-11-20 14:20: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-03 08:40:09 +01:00
}
2014-11-20 14:20:09 +01:00
void func13 ( ) {
2009-01-24 19:55:56 +01:00
check ( " static void f() \n "
" { \n "
" char *p = malloc(100); \n "
" foo(&p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-24 19:55:56 +01:00
}
2014-11-20 14:20:09 +01:00
void func14 ( ) {
2009-06-12 17:31:29 +02:00
// 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-12 17:31:29 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-01-24 19:55:56 +01:00
2014-11-20 14:20:09 +01:00
void func15 ( ) {
2009-06-16 19:05:05 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-06-16 19:05:05 +02:00
}
2014-11-20 14:20:09 +01:00
void func16 ( ) {
2009-08-18 20:49:08 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-08-18 20:49:08 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-06-16 19:05:05 +02:00
2014-11-20 14:20:09 +01:00
void func17 ( ) {
2010-02-06 22:35:36 +01:00
// 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-02-06 22:35:36 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void func18 ( ) {
2010-05-30 20:30:08 +02:00
// 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 "
2012-11-29 21:07:52 +01:00
" return strdup( \" \" ); \n "
2010-05-30 20:30:08 +02:00
" } \n "
" \n "
" static void bar() \n "
" { \n "
" int *p = malloc(16); \n "
" free_pointers(1, p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-05-30 20:30:08 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void func19 ( ) {
2010-09-19 12:16:29 +02:00
// 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-09-19 12:16:29 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void func20 ( ) {
2010-11-10 18:24:40 +01:00
// 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-11-10 18:24:40 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-11-10 18:24:40 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-03-20 21:52:25 +01:00
//# Ticket 2569
2014-11-20 14:20:09 +01:00
void func21 ( ) {
2011-03-20 22:17:51 +01:00
// checking for lstat function:
// ----------------------------
2011-03-20 21:52:25 +01:00
check ( " void foo () \n "
" { \n "
" struct stat CFileAttr; \n "
" char *cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if (lstat (cpFile, &CFileAttr) != 0) \n "
" { \n "
" return; \n "
" } \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2010-05-30 20:30:08 +02:00
2011-03-20 21:52:25 +01:00
check ( " void foo () \n "
" { \n "
" struct stat CFileAttr; \n "
" char *cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if (lstat (cpFile, &CFileAttr) != 0) \n "
" { \n "
" delete [] cpFile; \n "
" return; \n "
" } \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2010-05-30 20:30:08 +02:00
2011-03-20 21:52:25 +01:00
check ( " void foo () \n "
" { \n "
" struct stat CFileAttr; \n "
" char *cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if (lstat (cpFile, &CFileAttr) != 0) \n "
" { \n "
" delete [] cpFile; \n "
" return; \n "
" } \n "
" delete [] cpFile; \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-20 22:17:51 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
/// checking for stat function:
// ----------------------------
check ( " void foo () \n "
" { \n "
" struct stat CFileAttr; \n "
" char *cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if ( stat (cpFile, &CFileAttr) != 0) \n "
" { \n "
" return; \n "
" } \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-20 22:17:51 +01:00
check ( " void foo () \n "
" { \n "
" struct stat CFileAttr; \n "
" char *cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if ( stat (cpFile, &CFileAttr) != 0) \n "
" { \n "
" delete [] cpFile; \n "
" return; \n "
" } \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-20 22:17:51 +01:00
check ( " void foo () \n "
" { \n "
" struct stat CFileAttr; \n "
" char *cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if ( stat (cpFile, &CFileAttr) != 0) \n "
" { \n "
" delete [] cpFile; \n "
" return; \n "
" } \n "
" delete [] cpFile; \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-20 23:39:44 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// checking for access function
// http://www.gnu.org/s/libc/manual/html_node/Testing-File-Access.html
// --------------------------------------------------------------------
check ( " void foo () \n "
" { \n "
" struct stat CFileAttr; \n "
" char *cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if ( access (cpFile, R_OK) != 0) \n "
" { \n "
" return; \n "
" } \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-20 23:39:44 +01:00
check ( " void foo () \n "
" { \n "
" struct stat CFileAttr; \n "
" char *cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if (access (cpFile, R_OK) != 0) \n "
" { \n "
" delete [] cpFile; \n "
" return; \n "
" } \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-20 23:39:44 +01:00
check ( " void foo () \n "
" { \n "
" struct stat CFileAttr; \n "
" char *cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if (access (cpFile, R_OK) != 0) \n "
" { \n "
" delete [] cpFile; \n "
" return; \n "
" } \n "
" delete [] cpFile; \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-21 00:07:37 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// checking for chdir function
// http://home.fhtw-berlin.de/~junghans/cref/MAN/chdir.htm
// --------------------------------------------------------
check ( " void foo() \n "
" { \n "
" char * cpDir = new char [7]; \n "
" strcpy (cpDir, \" /home/ \" ); \n "
" if (chdir (cpDir) != 0) \n "
" { \n "
" return; \n "
" } \n "
" delete [] cpDir; \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Memory leak: cpDir \n " , errout . str ( ) ) ;
2011-03-21 00:07:37 +01:00
check ( " void foo() \n "
" { \n "
" char * cpDir = new char [7]; \n "
" strcpy (cpDir, \" /home/ \" ); \n "
" if (chdir (cpDir) != 0) \n "
" { \n "
" delete [] cpDir; \n "
" return; \n "
" } \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: cpDir \n " , errout . str ( ) ) ;
2011-03-21 00:07:37 +01:00
check ( " void foo() \n "
" { \n "
" char * cpDir = new char [7]; \n "
" strcpy (cpDir, \" /home/ \" ); \n "
" if (chdir (cpDir) != 0) \n "
" { \n "
" delete [] cpDir; \n "
" return; \n "
" } \n "
" delete [] cpDir; \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-21 00:07:37 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// checking for chmod function
// http://publib.boulder.ibm.com/infocenter/zos/v1r10/index.jsp?topic=/com.ibm.zos.r10.bpxbd00/rtchm.htm
// ------------------------------------------------------------------------------------------------------
check ( " void foo() \n "
" { \n "
" char * cpDir = new char [7]; \n "
" strcpy (cpDir, \" /home/ \" ); \n "
" if (chmod(cpDir, S_IRWXU|S_IRWXG) != 0) \n "
" { \n "
" return; \n "
" } \n "
" delete [] cpDir; \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Memory leak: cpDir \n " , errout . str ( ) ) ;
2011-03-21 00:07:37 +01:00
check ( " void foo() \n "
" { \n "
" char * cpDir = new char [7]; \n "
" strcpy (cpDir, \" /home/ \" ); \n "
" if (chmod(cpDir, S_IRWXU|S_IRWXG) != 0) \n "
" { \n "
" delete [] cpDir; \n "
" return; \n "
" } \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: cpDir \n " , errout . str ( ) ) ;
2011-03-21 00:07:37 +01:00
check ( " void foo() \n "
" { \n "
" char * cpDir = new char [7]; \n "
" strcpy (cpDir, \" /home/ \" ); \n "
" if (chmod(cpDir, S_IRWXU|S_IRWXG) != 0) \n "
" { \n "
" delete [] cpDir; \n "
" return; \n "
" } \n "
" delete [] cpDir; \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-21 00:07:37 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// checking for chown function
// http://publib.boulder.ibm.com/infocenter/zos/v1r10/index.jsp?topic=/com.ibm.zos.r10.bpxbd00/rtchm.htm
// ------------------------------------------------------------------------------------------------------
check ( " void foo() \n "
" { \n "
" char * cpDir = new char [7]; \n "
" strcpy (cpDir, \" /home/ \" ); \n "
" if (chown(cpDir, 25, 0) != 0) \n "
" { \n "
" return; \n "
" } \n "
" delete [] cpDir; \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Memory leak: cpDir \n " , errout . str ( ) ) ;
2011-03-21 00:07:37 +01:00
check ( " void foo() \n "
" { \n "
" char * cpDir = new char [7]; \n "
" strcpy (cpDir, \" /home/ \" ); \n "
" if (chown(cpDir, 25, 0) != 0) \n "
" { \n "
" delete [] cpDir; \n "
" return; \n "
" } \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: cpDir \n " , errout . str ( ) ) ;
2011-03-21 00:07:37 +01:00
check ( " void foo() \n "
" { \n "
" char * cpDir = new char [7]; \n "
" strcpy (cpDir, \" /home/ \" ); \n "
" if (chown(cpDir, 25, 0) != 0) \n "
" { \n "
" delete [] cpDir; \n "
" return; \n "
" } \n "
" delete [] cpDir; \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-20 21:52:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-21 17:43:26 +01:00
// checking perror
//http://www.cplusplus.com/reference/clibrary/cstdio/perror/
// ---------------------------------------------------------
check ( " void foo() \n "
" { \n "
" char *cBuf = new char[11]; \n "
" sprintf(cBuf, \" %s \" , \" testtest.. \" ); \n "
" perror (cBuf); \n "
" delete [] cBuf; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-21 17:43:26 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" char *cBuf = new char[11]; \n "
" sprintf(cBuf, \" %s \" , \" testtest.. \" ); \n "
" perror (cBuf); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Memory leak: cBuf \n " , errout . str ( ) ) ;
2011-03-20 21:52:25 +01:00
}
2008-12-18 22:28:57 +01:00
2011-03-21 15:12:21 +01:00
// # 2668
2014-11-20 14:20:09 +01:00
void func22 ( ) {
2011-03-21 15:12:21 +01:00
check ( " void foo() \n "
" { \n "
" char * cpFile; \n "
" cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if(freopen(cpFile, \" w \" ,stdout)==0) \n "
" { \n "
" return; \n "
" } \n "
" delete [] cpFile; \n "
" fclose (stdout); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-21 15:12:21 +01:00
check ( " void foo() \n "
" { \n "
" char * cpFile; \n "
" cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if(freopen(cpFile, \" w \" ,stdout)==0) \n "
" { \n "
" delete [] cpFile; \n "
" return; \n "
" } \n "
" fclose (stdout); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:12]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-21 15:12:21 +01:00
check ( " void foo() \n "
" { \n "
" char * cpFile; \n "
" cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" if(freopen(cpFile, \" w \" ,stdout)==0) \n "
" { \n "
" delete [] cpFile; \n "
" return; \n "
" } \n "
" delete [] cpFile; \n "
" fclose (stdout); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-21 15:12:21 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-03-21 23:20:46 +01:00
// # 2667
2014-11-20 14:20:09 +01:00
void func23 ( ) {
2011-03-22 00:59:53 +01:00
2011-03-21 23:20:46 +01:00
// check open() function
// ----------------------
check ( " int * foo() \n "
" { \n "
" char * cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" int file=open(cpFile,O_RDONLY); \n "
" if(file < -1) \n "
" { \n "
" return file; \n "
" } \n "
" delete [] cpFile; \n "
" return file; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-21 23:20:46 +01:00
check ( " int * foo() \n "
" { \n "
" char * cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" int file=open(cpFile,O_RDONLY); \n "
" if(file < -1) \n "
" { \n "
" delete [] cpFile; \n "
" return file; \n "
" } \n "
" return file; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-21 23:20:46 +01:00
check ( " int * foo() \n "
" { \n "
" char * cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" int file=open(cpFile,O_RDONLY); \n "
" if(file < -1) \n "
" { \n "
" delete [] cpFile; \n "
" return file; \n "
" } \n "
" delete [] cpFile; \n "
" return file; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-21 23:20:46 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// check for _open, _wopen
// http://msdn.microsoft.com/en-us/library/z0kc8e3z(VS.80).aspx
// -------------------------------------------------------------
check ( " int * foo() \n "
" { \n "
" char * cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" int file=_open(cpFile,_O_RDONLY); \n "
" if(file == -1) \n "
" { \n "
" return file; \n "
" } \n "
" delete [] cpFile; \n "
" return file; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-21 23:20:46 +01:00
check ( " int * foo() \n "
" { \n "
" char * cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" int file=_open(cpFile,_O_RDONLY); \n "
" if(file == -1) \n "
" { \n "
" delete [] cpFile; \n "
" return file; \n "
" } \n "
" return file; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: cpFile \n " , errout . str ( ) ) ;
2011-03-21 23:20:46 +01:00
check ( " int * foo() \n "
" { \n "
" char * cpFile = new char [13]; \n "
" strcpy (cpFile, \" testfile.txt \" ); \n "
" int file=_open(cpFile,_O_RDONLY); \n "
" if(file == -1) \n "
" { \n "
" delete [] cpFile; \n "
" return file; \n "
" } \n "
" delete [] cpFile; \n "
" return file; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-21 23:20:46 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-04-04 23:29:18 +02:00
// #2705
2014-11-20 14:20:09 +01:00
void func24 ( ) {
2012-12-06 19:19:22 +01:00
check ( " void f(void) \n "
2011-04-04 23:29:18 +02:00
" { \n "
" std::string *x = new std::string; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2015-11-18 20:33:39 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: x \n " , errout . str ( ) ) ;
2011-04-04 23:29:18 +02:00
2012-12-06 19:19:22 +01:00
check ( " void f(void) \n "
2011-04-04 23:29:18 +02:00
" { \n "
" std::string *x = new std::string; \n "
" delete x; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-04-05 04:25:56 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-04-04 23:29:18 +02:00
}
2014-11-20 14:20:09 +01:00
void func25 ( ) { // ticket #2904
2011-07-15 01:15:59 +02:00
check ( " class Fred { }; \n "
2012-12-06 19:19:22 +01:00
" void f(void) \n "
2011-07-15 01:15:59 +02:00
" { \n "
" Fred *f = new Fred(); \n "
" delete f; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-07-15 01:15:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class Fred { }; \n "
2012-12-06 19:19:22 +01:00
" void f(void) \n "
2011-07-15 01:15:59 +02:00
" { \n "
" Fred *f = new Fred(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: f \n " , errout . str ( ) ) ;
2011-07-15 02:45:27 +02:00
check ( " class Fred { void foo(){ } }; \n "
2012-12-06 19:19:22 +01:00
" void f(void) \n "
2011-07-15 02:45:27 +02:00
" { \n "
" Fred *f = new Fred(); \n "
" delete f; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-07-15 02:45:27 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class Fred { void foo(){ } }; \n "
2012-12-06 19:19:22 +01:00
" void f(void) \n "
2011-07-15 02:45:27 +02:00
" { \n "
" Fred *f = new Fred(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: f \n " , errout . str ( ) ) ;
2011-07-15 01:15:59 +02:00
}
2014-11-20 14:20:09 +01:00
void func26 ( ) { // ticket #3444
2012-07-02 10:01:37 +02:00
// technically there is a leak here. However warning is not wanted
2011-12-29 07:35:27 +01:00
check ( " void f() { \n "
" char *p = strdup( \" A=B \" ); \n "
" putenv(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-11-07 22:50:57 +01:00
2014-11-20 14:20:09 +01:00
void func27 ( ) { // ticket #2773
2012-07-02 10:01:37 +02:00
check ( " void f(FRED *pData) \n "
" { \n "
" pData =(FRED*)malloc( 100 ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-07-02 10:01:37 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: pData \n " , errout . str ( ) ) ;
check ( " void f(int *pData) \n "
" { \n "
" pData =(int*)malloc( 100 ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-07-02 10:01:37 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: pData \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void func28 ( ) { // ticket #3236
2014-02-01 12:51:29 +01:00
check ( " void f() \n "
" { \n "
" my_struct *p = malloc(42); \n "
" p->a + p->b; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void allocfunc1 ( ) {
2009-06-15 17:44:59 +02:00
check ( " static char *a() \n "
" { \n "
" return new char[100]; \n "
" } \n "
" static void b() \n "
" { \n "
" char *p = a(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
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
2014-11-20 14:20:09 +01:00
void allocfunc2 ( ) {
2009-08-05 21:18:16 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2014-04-02 17:33:04 +02:00
ASSERT_EQUALS ( " " , 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2014-04-02 17:33:04 +02:00
ASSERT_EQUALS ( " " , 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 "
" free(p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2014-04-02 17:33:04 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-05 21:18:16 +02:00
}
2014-11-20 14:20:09 +01:00
void allocfunc3 ( ) {
2010-04-24 20:40:57 +02:00
check ( " static char *a() \n "
" { \n "
" char *data = malloc(10);; "
" return data; \n "
" } \n "
" static void b() \n "
" { \n "
" char *p = a(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:8]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
2010-04-24 20:40:57 +02:00
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +01:00
void allocfunc4 ( ) {
2010-05-09 13:46:13 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:11]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
2010-05-09 13:46:13 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-05-09 13:46:13 +02:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:11]: (error) Mismatching allocation and deallocation: p \n " ) , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void allocfunc5 ( ) {
2010-06-05 01:58:50 +02:00
check ( " void foo(char **str) \n "
" { \n "
" *str = malloc(20); \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *p; \n "
" foo(&p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:10]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
2010-06-05 01:58:50 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-06-05 01:58:50 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( std : : string ( " [test.cpp:11]: (error) Memory leak: p \n " ) , errout . str ( ) ) ;
2010-06-05 01:58:50 +02:00
check ( " void foo(char **str) \n "
" { \n "
2012-09-11 18:03:47 +02:00
" char *a = malloc(20); \n "
2010-06-05 01:58:50 +02:00
" *str = a; \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *p; \n "
" foo(&p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
TODO_ASSERT_EQUALS ( std : : string ( " [test.cpp:11]: (error) Memory leak: p \n " ) ,
2011-01-30 12:54:19 +01:00
" " , 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2014-04-02 17:33:04 +02:00
ASSERT_EQUALS ( " " , 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2014-04-02 17:33:04 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-01-04 11:46:26 +01:00
check ( " int alloc(char **str) { \n "
" *str = malloc(20); \n "
" if (condition) { free(str); return -123; } \n "
" return 0; \n "
" } \n "
" \n "
" void bar() \n "
" { \n "
" char *p; \n "
" if ((ret = alloc(&p)) != 0) return; \n "
" free(p); \n "
" } " ) ;
2018-01-05 22:03:49 +01:00
ASSERT_EQUALS ( std : : string ( ) , errout . str ( ) ) ;
2010-06-05 01:58:50 +02:00
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +01:00
void allocfunc6 ( ) {
2010-06-30 09:21:15 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2014-04-02 17:33:04 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-30 09:21:15 +02:00
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +01:00
void allocfunc7 ( ) {
2010-12-29 22:18:23 +01:00
// Ticket #2374 - no false positive
check ( " char *data() \n "
" { \n "
" char *s = malloc(100); \n "
" strings[0] = s; \n "
" return s; \n "
" } \n "
" \n "
" static void foo() \n "
" { \n "
" char* s = data(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-19 14:05:22 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-12-27 08:12:37 +01:00
// #5144
check ( " C* BuildC( C *previous ) { \n "
" C *result = malloc(100); \n "
" result->previous = previous; \n "
" return result; \n "
" } \n "
" C *ParseC( ) { \n "
" C *expr1 = NULL; \n "
" while( something() ) \n "
" expr1 = BuildC(expr1); \n "
" return expr1; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-29 22:18:23 +01:00
}
2014-11-20 14:20:09 +01:00
void allocfunc8 ( ) {
2011-03-19 14:05:22 +01:00
// Ticket #2213 - calling alloc function twice
check ( " FILE *foo() { \n "
" return fopen(a,b); \n "
" } \n "
" \n "
" void bar() { \n "
" FILE *f = foo(); \n "
" f = foo(); \n "
" fclose(f); \n "
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Resource leak: f \n " , errout . str ( ) ) ;
2011-03-19 14:05:22 +01:00
}
2010-12-29 22:18:23 +01:00
2014-11-20 14:20:09 +01:00
void allocfunc9 ( ) {
2011-03-24 17:14:12 +01:00
// Ticket #2673 - address is taken in alloc func
check ( " char *addstring(const char *s) { \n "
" char *ret = strdup(s); \n "
" strings.push_back(ret); "
" return ret; \n "
" } \n "
" \n "
" void foo() { \n "
" char *s = addstring( \" abc \" ); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void allocfunc10 ( ) {
2011-07-24 16:08:29 +02:00
// Ticket #2921 - static pointer
check ( " char *getstr() { \n "
" static char *ret = malloc(100); \n "
" return ret; \n "
" } \n "
" \n "
" void foo() { \n "
" char *s = getstr(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +01:00
void allocfunc11 ( ) { // ticket #3809 - false positive
2012-06-01 19:01:19 +02:00
check ( " void f (double * & data_val) { \n "
" data_val = malloc(0x100); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-06-01 19:01:19 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-05-29 21:44:39 +02:00
}
2014-11-20 14:20:09 +01:00
void allocfunc12 ( ) { // #3660: allocating and returning non-local pointer => not allocfunc
2012-06-25 20:00:50 +02:00
check ( " char *p; \n " // global pointer
" char *a() { \n "
" if (!p) p = malloc(10); \n "
" return p; \n "
" } \n "
" void b() { \n "
" char *x = a(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void allocfunc13 ( ) { // #4494: class function
2013-01-22 21:33:39 +01:00
check ( " namespace n { \n "
" char *a() { return malloc(100); } \n "
" } \n "
" void b() { \n "
" char *x = n::a(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Memory leak: x \n " , errout . str ( ) ) ;
2013-01-31 17:00:50 +01:00
check ( " class C { \n " // ¤4540
" char *a() { return malloc(100); } \n "
" } \n "
" void b() { \n "
" C c; "
" char *x = c.a(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Memory leak: x \n " , errout . str ( ) ) ;
2013-04-03 10:12:36 +02:00
check ( " class Pool{ \n "
" int* GetNewObj() \n "
" { \n "
2013-04-09 09:49:58 +02:00
" return new int; \n "
2013-04-03 10:12:36 +02:00
" } \n "
" }; \n "
" void foo(){ \n "
" Pool pool; \n "
" int* a = pool.GetNewObj(); \n "
" int* b = GetNewObj(); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2013-01-22 21:33:39 +01:00
}
2015-01-05 13:23:38 +01:00
void allocfunc14 ( ) { // use pointer before returning it
check ( " static struct ABC * newabc() { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" init_abc(&abc->a); \n " // <- might take address
" return abc; \n "
" } \n "
" \n "
" static void f() { \n "
" struct ABC *abc = newabc(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2016-05-26 17:42:27 +02:00
void inlineFunction ( ) { // #3989 - inline function
check ( " int test() { \n "
" char *c; \n "
" int ret() { \n "
" free(c); \n "
" return 0; \n "
" } \n "
" c = malloc(128); \n "
" return ret(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2008-12-18 22:28:57 +01:00
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: str \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
}
2014-11-20 14:20:09 +01:00
void linux_list_2 ( ) { // #5993
2014-11-07 07:44:12 +01:00
check ( " void foo() { \n "
" struct AB *ab = malloc(sizeof(struct AB)); \n "
" list_add_tail(&(ab->list)); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2014-02-02 00:10:26 +01:00
ASSERT_EQUALS ( " [test.cpp:12]: (error) Memory leak: s2 \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-08 14:35:09 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' a \' nulled but not freed upon failure \n "
2011-11-30 19:43:02 +01:00
" [test.cpp:5]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2008-12-18 22:28:57 +01:00
2011-01-08 14:35:09 +01: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
}
2014-11-20 14:20:09 +01:00
void realloc3 ( ) {
2009-03-22 21:42:01 +01:00
check ( " void foo() \n "
" { \n "
" char *a = 0; \n "
" if ((a = realloc(a, 100)) == NULL) \n "
" return; \n "
" free(a); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-03-22 21:42:01 +01:00
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-03-22 21:42:01 +01:00
}
2014-11-20 14:20:09 +01:00
void realloc4 ( ) {
2009-03-28 16:13:06 +01:00
check ( " void foo() \n "
" { \n "
" static char *a = 0; \n "
" if ((a = realloc(a, 100)) == NULL) \n "
" return; \n "
" free(a); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-03-28 16:13:06 +01:00
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: a \n " ,
" [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
}
2014-11-20 14:20:09 +01:00
void realloc5 ( ) {
2009-08-02 21:23:47 +02:00
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 "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2010-05-16 19:55:16 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-02 21:23:47 +02:00
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +01: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
}
2014-11-20 14:20:09 +01:00
void realloc7 ( ) {
2010-07-19 08:55:39 +02:00
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 "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2010-07-19 08:55:39 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void realloc8 ( ) {
2010-07-27 08:17:27 +02:00
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 "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2010-07-27 08:17:27 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void realloc9 ( ) {
2010-08-24 20:58:22 +02:00
check ( " void foo() \n "
" { \n "
" x = realloc(x,100); \n "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2010-08-24 20:58:22 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void realloc10 ( ) {
2010-09-11 11:15:04 +02:00
check ( " void foo() { \n "
" char *pa, *pb; \n "
" pa = pb = malloc(10); \n "
" pa = realloc(pa, 20); "
" exit(); \n "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2010-09-11 11:15:04 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void realloc11 ( ) {
2011-01-13 07:33:46 +01:00
check ( " void foo() { \n "
" char *p; \n "
" p = realloc(p, size); \n "
" if (!p) \n "
" error(); \n "
" usep(p); \n "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2011-01-13 07:33:46 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void realloc12 ( ) {
2011-10-11 22:07:14 +02:00
check ( " void foo(int x) \n "
" { \n "
" char *a = 0; \n "
" if ((a = realloc(a, x + 100)) == NULL) \n "
" return; \n "
" free(a); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-10-11 22:07:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void realloc13 ( ) {
2011-10-11 22:07:14 +02:00
check ( " void foo() \n "
" { \n "
" char **str; \n "
" *str = realloc(*str,100); \n "
" free (*str); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-10-11 22:07:14 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' str \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void realloc14 ( ) {
2011-10-11 22:07:14 +02:00
check ( " void foo() { \n "
" char *p; \n "
" p = realloc(p, size + 1); \n "
" if (!p) \n "
" error(); \n "
" usep(p); \n "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2011-10-11 22:07:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void realloc15 ( ) {
2011-11-25 07:23:54 +01:00
check ( " bool foo() { \n "
" char ** m_options; \n "
" m_options = (char**)realloc( m_options, 2 * sizeof(char*)); \n "
" if( m_options == NULL ) \n "
" return false; \n "
" return true; \n "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2012-05-03 10:43:47 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Common realloc mistake: \' m_options \' nulled but not freed upon failure \n "
" [test.cpp:6]: (error) Memory leak: m_options \n " , errout . str ( ) ) ;
2011-11-25 07:23:54 +01:00
}
2014-11-20 14:20:09 +01:00
void realloc16 ( ) {
2014-03-17 16:10:54 +01:00
check ( " void f(char *zLine) { \n "
" zLine = realloc(zLine, 42); \n "
" if (zLine) { \n "
" free(zLine); \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign1 ( ) {
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01: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 "
2013-03-20 15:36:16 +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 "
2013-03-20 15:36:16 +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 "
2013-03-20 15:36:16 +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 "
2013-03-20 15:36:16 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-05-29 17:44:10 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-08-19 19:42:07 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2014-02-02 00:10:26 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void dealloc_use ( ) {
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-21 13:04:13 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2008-12-31 10:02:45 +01:00
2013-12-14 07:37:24 +01:00
check ( " void f() \n "
" { \n "
" char *s = new char[100]; \n "
" delete [] s; \n "
" printf( \" %p \\ n \" , s); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-30 12:54:19 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released \n " ,
" " , 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-25 17:36:46 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-10-26 17:49:48 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-05 21:17:01 +01:00
}
2014-11-20 14:20:09 +01:00
void dealloc_use_2 ( ) {
2011-08-23 23:18:47 +02:00
// #3041 - assigning pointer when it's used
check ( " void f(char *s) { \n "
" free(s); \n "
" strcpy(a, s=b()); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-08-23 23:18:47 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-01-15 21:34:39 +01:00
2014-11-20 14:20:09 +01:00
void dealloc_use_3 ( ) {
2011-08-31 05:42:11 +02:00
check ( " void foo() \n "
" { \n "
" char *str = malloc(10); \n "
" realloc(str, 0); \n "
" str[10] = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-08-31 05:42:11 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" char *str = realloc(0, 10); \n "
" realloc(str, 0); \n "
" str[10] = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-08-31 05:42:11 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released \n " , errout . str ( ) ) ;
}
2017-03-25 20:46:25 +01:00
void dealloc_use_4 ( ) { // #7960
check ( " class SR { \n "
" public: \n "
" void dostuff(); \n "
" int* m_data; \n "
" }; \n "
" void SR::dostuff() { \n "
" SR sr; \n "
" delete m_data; \n "
" sr.m_data = new SVec; \n "
" *m_data = 123; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
}
2014-11-20 14:20:09 +01:00
void freefree2 ( ) {
2009-01-16 17:29:41 +01:00
check ( " void foo() \n "
" { \n "
" FILE *fd = fopen( \" test.txt \" , \" wb \" ); \n "
" fprintf(fd, \" test \" ); \n "
" fclose(fd); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-01-16 17:29:41 +01:00
}
2014-11-20 14:20:09 +01:00
void freefree3 ( ) {
2012-10-25 19:41:18 +02:00
check ( " void foo() \n "
" { \n "
" char *p = malloc(10); \n "
" free(p); \n "
" bar(&p); \n "
" free(p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-10-25 19:41:18 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void strcpy_result_assignment ( ) {
2009-06-06 20:55:16 +02:00
check ( " void foo() \n "
" { \n "
" char *p1 = malloc(10); \n "
" char *p2 = strcpy(p1, \" a \" ); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +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
2014-11-20 14:20:09 +01:00
void all1 ( ) {
2009-01-31 14:57:27 +01:00
check ( " void foo() \n "
" { \n "
" Fred *f = new Fred; \n "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
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
2014-11-20 14:20:09 +01:00
void malloc_constant_1 ( ) {
2009-02-07 11:54:39 +01:00
check ( " void foo() \n "
" { \n "
" int *p = malloc(3); \n "
" free(p); \n "
2013-05-23 06:34:22 +02:00
" } \n " ) ;
2014-09-02 09:38:40 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) The allocated size 3 is not a multiple of the underlying type's size. \n " , errout . str ( ) ) ;
2009-02-07 11:54:39 +01:00
}
2009-02-08 09:21:15 +01:00
2014-11-20 14:20:09 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-02-08 09:21:15 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-02-08 12:59:04 +01:00
}
2014-11-20 14:20:09 +01:00
void unknownFunction2 ( ) {
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-02-08 09:21:15 +01:00
}
2014-11-20 14:20:09 +01:00
void unknownFunction4 ( ) {
2009-06-21 13:48:39 +02:00
check ( " void foo() \n "
" { \n "
" int *p = new int[100]; \n "
" a(); \n "
" if (b) return; \n "
" delete [] p; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-06-21 13:48:39 +02:00
}
2014-11-20 14:20:09 +01:00
void unknownFunction5 ( ) {
2009-06-23 18:29:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-23 18:29:43 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-02-20 07:28:18 +01:00
2014-11-20 14:20:09 +01:00
void class1 ( ) {
2009-12-30 21:29:54 +01:00
check ( " class Fred \n "
" { \n "
" public: \n "
" Fred() \n "
" { \n "
" int *p = new int[100]; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-12-30 21:29:54 +01:00
}
2014-11-20 14:20:09 +01:00
void class2 ( ) {
2011-03-07 20:17:52 +01:00
check ( " class Fred { \n "
" public: \n "
" Fred() : rootNode(0) {} \n "
" \n "
" private: \n "
" struct Node { \n "
" Node(Node* p) { \n "
" parent = p; \n "
" if (parent) { \n "
" parent->children.append(this); \n "
" } \n "
" } \n "
" \n "
" ~Node() { \n "
" qDeleteAll(children); \n "
" } \n "
" \n "
" QList<Node*> children; \n "
" }; \n "
" \n "
" Node rootNode; \n "
" \n "
" void f() { \n "
" Node* recordNode = new Node(&rootNode); \n "
" } \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-12-30 21:29:54 +01:00
2014-11-20 14:20:09 +01:00
void autoptr1 ( ) {
2009-04-28 20:01:35 +02:00
check ( " std::auto_ptr<int> foo() \n "
" { \n "
" int *i = new int; \n "
" return std::auto_ptr<int>(i); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void if_with_and ( ) {
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 "
2015-10-07 18:33:57 +02:00
" } " , false , false , 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 "
2015-10-07 18:33:57 +02:00
" } " , false , false , 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
2014-11-20 14:20:09 +01:00
void assign_pclose ( ) {
2015-02-15 18:11:09 +01:00
check ( " void f() { \n "
2009-05-06 20:20:25 +02:00
" FILE *f = popen ( \" test \" , \" w \" ); \n "
" int a = pclose(f); \n "
2015-10-07 18:33:57 +02:00
" } " , false , true ) ;
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
2017-01-14 12:16:47 +01:00
void conditional_dealloc_return ( ) { // #7820
check ( " void f() { \n "
" FILE *pPipe = popen( \" foo \" , \" r \" ); \n "
" if (feof(pPipe)) \n "
" pclose(pPipe); \n "
" return; \n "
" } " , /*c=*/ true , /*posix=*/ true ) ;
ASSERT_EQUALS ( " [test.c:5]: (error) Resource leak: pPipe \n " , errout . str ( ) ) ;
check ( " extern int bar(); \n "
" void f() { \n "
" char *c = (char*) malloc(10); \n "
" if (bar()) \n "
" free(c); \n "
" return; \n "
" } " , /*c=*/ true ) ;
ASSERT_EQUALS ( " [test.c:6]: (error) Memory leak: c \n " , errout . str ( ) ) ;
check ( " extern int bar(); \n "
" extern int baz(); \n "
" extern void bos(char*); \n "
" void f() { \n "
" char *c; \n "
" if(bar()) { \n "
" bos(c); \n "
" c = (char*) malloc(10); \n "
" if (baz()) \n "
" free(c); \n "
" }; \n "
" } " , /*c=*/ true ) ;
ASSERT_EQUALS ( " [test.c:11]: (error) Memory leak: c \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void exit2 ( ) {
2009-05-10 08:01:38 +02:00
check ( " void f() \n "
" { \n "
" char *out = new char[100]; \n "
" exit(0); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-07 08:55:20 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-10 08:01:38 +02:00
}
2009-05-12 21:04:49 +02:00
2014-11-20 14:20:09 +01:00
void exit4 ( ) {
2009-07-23 16:30:30 +02:00
check ( " void f() \n "
" { \n "
" char *p = malloc(100); \n "
" if (x) \n "
" { \n "
" exit(0); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-07-23 16:30:30 +02:00
}
2014-11-20 14:20:09 +01:00
void exit5 ( ) {
2009-08-04 21:34:14 +02:00
check ( " void f() \n "
" { \n "
" char *p = malloc(100); \n "
" if (p) \n "
" { \n "
" xyz(); \n "
" exit(0); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-08-04 21:34:14 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void exit6 ( ) {
2009-12-03 19:19:20 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-12-03 19:19:20 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void exit7 ( ) {
2011-01-01 20:14:01 +01:00
check ( " int a(int x) { \n "
" if (x == 0) { \n "
" exit(0); \n "
" } \n "
" return x + 2; \n "
" } \n "
" \n "
" void b() { \n "
" char *p = malloc(100); \n "
" int i = a(123); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2011-01-01 20:14:01 +01:00
}
2014-11-20 14:20:09 +01:00
void noreturn ( ) {
2009-11-14 09:06:28 +01:00
check ( " void fatal_error() \n "
" { exit(1); } \n "
" \n "
" void f() \n "
" { \n "
" char *p = malloc(100); \n "
" fatal_error(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-11-14 09:06:28 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-11 20:14:15 +01:00
check ( " void fatal_error() \n " // #2440
" { } \n "
" \n "
" void f() \n "
" { \n "
" char *p = malloc(100); \n "
" fatal_error(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-11-14 09:06:28 +01:00
}
2014-11-20 14:20:09 +01:00
void strndup_function ( ) {
2015-02-15 15:56:05 +01:00
check ( " void f() { \n "
2009-05-19 22:29:10 +02:00
" char *out = strndup( \" text \" , 3); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2015-02-15 15:56:05 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: out \n " , errout . str ( ) ) ;
2009-05-19 22:29:10 +02:00
}
2014-11-20 14:20:09 +01:00
void tmpfile_function ( ) {
2009-06-01 12:40:24 +02:00
check ( " void f() \n "
" { \n "
" FILE *f = tmpfile(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: f \n " , errout . str ( ) ) ;
2009-06-01 12:40:24 +02:00
check ( " void f() \n "
" { \n "
" FILE *f = tmpfile(); \n "
" if (!f) \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Resource leak: f \n " , errout . str ( ) ) ;
2009-06-01 12:40:24 +02:00
check ( " void f() \n "
" { \n "
" FILE *f = tmpfile(); \n "
" fclose(f); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-01 12:40:24 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" FILE *f = tmpfile(); \n "
" if (!f) \n "
" return; \n "
" fclose(f); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-01 12:40:24 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " FILE *f() \n "
" { \n "
" return tmpfile(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-01 12:40:24 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void fcloseall_function ( ) {
2009-05-22 16:47:40 +02:00
check ( " void f() \n "
" { \n "
" FILE *f = fopen(fname, str); \n "
" fcloseall(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-05 02:39:36 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-05-22 16:47:40 +02:00
}
2014-11-20 14:20:09 +01:00
void open_function ( ) {
2009-06-21 17:01:43 +02:00
check ( " void f(const char *path) \n "
" { \n "
" int fd = open(path, O_RDONLY); \n "
2015-10-07 18:33:57 +02:00
" } " , false , true , true ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: fd \n " , errout . str ( ) ) ;
2009-06-21 17:01:43 +02:00
check ( " void f(const char *path) \n "
" { \n "
" int fd = open(path, O_RDONLY); \n "
" if (fd == -1) \n "
" return; \n "
" close(fd); \n "
2015-10-07 18:33:57 +02:00
" } " , false , true , true ) ;
2009-06-21 17:01:43 +02:00
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 "
2015-10-07 18:33:57 +02:00
" } " , false , true , true ) ;
2009-06-21 17:01:43 +02:00
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 "
2015-10-07 18:33:57 +02:00
" } " , false , true , true ) ;
2009-11-30 16:45:19 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-06-20 18:42:13 +02:00
}
2014-11-20 14:20:09 +01:00
void creat_function ( ) {
2009-06-21 17:01:43 +02:00
check ( " void f(const char *path) \n "
" { \n "
" int fd = creat(path, S_IRWXU); \n "
2015-10-07 18:33:57 +02:00
" } " , false , true ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Resource leak: fd \n " , errout . str ( ) ) ;
2009-06-21 17:01:43 +02:00
}
2014-11-20 14:20:09 +01:00
void close_function ( ) {
2009-06-21 17:01:43 +02:00
check ( " void f(const char *path) \n "
" { \n "
" int fd = open(path, O_RDONLY); \n "
" close(fd); \n "
2015-10-07 18:33:57 +02:00
" } " , false , true ) ;
2009-06-21 17:01:43 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(const char *path) \n "
" { \n "
" int fd = creat(path, S_IRWXU); \n "
" close(fd); \n "
2015-10-07 18:33:57 +02:00
" } " , false , true ) ;
2009-06-21 17:01:43 +02:00
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 "
2015-10-07 18:33:57 +02:00
" } " , false , true ) ;
2009-06-21 17:01:43 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-10 22:49:34 +02:00
//#ticket 1401
check ( " int myfunc() \n "
" { \n "
" int handle; \n "
2012-12-06 19:19:22 +01:00
" \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 "
2012-12-06 19:19:22 +01:00
" \n "
" while (some_condition()) \n "
2010-06-10 22:49:34 +02:00
" if (some_other_condition()) \n "
" { \n "
" close(handle); \n "
" return 3; \n "
" } \n "
" close(handle); \n "
2015-10-07 18:33:57 +02:00
" } " , false , true ) ;
2010-06-10 22:49:34 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
//#ticket 1401
check ( " int myfunc() \n "
" { \n "
" int handle; \n "
2012-12-06 19:19:22 +01:00
" \n "
2012-03-18 07:49:22 +01:00
" handle = open( \" myfile \" , O_RDONLY); \n "
2010-06-10 22:49:34 +02:00
" if (handle < 0) return 1; \n "
2012-12-06 19:19:22 +01:00
" \n "
" while (some_condition()) \n "
2010-06-10 22:49:34 +02:00
" if (some_other_condition()) \n "
" { \n "
" return 3; \n "
" } \n "
" close(handle); \n "
2015-10-07 18:33:57 +02:00
" } " , false , true ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:11]: (error) Resource leak: handle \n " , errout . str ( ) ) ;
2009-06-21 17:01:43 +02:00
}
2014-11-20 14:20:09 +01:00
void fd_functions ( ) {
2009-06-21 17:01:43 +02:00
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 "
2015-10-07 18:33:57 +02:00
" } " , false , true ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:24]: (error) Resource leak: fd \n " , errout . str ( ) ) ;
2009-06-21 17:01:43 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:22]: (error) Resource leak: f \n " , errout . str ( ) ) ;
2009-05-23 12:20:26 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Resource leak: fin1a \n " , errout . str ( ) ) ;
2009-07-18 13:32:55 +02:00
}
{
check ( " void f() \n "
" { \n "
" int c; \n "
" FILE *fin1b = fopen( \" FILE.txt \" , \" r \" ); \n "
" c = getc(fin1b); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (error) Resource leak: fin1b \n " , errout . str ( ) ) ;
2009-07-18 13:32:55 +02:00
}
}
2018-10-01 11:58:27 +02:00
void fclose_comma ( ) {
check ( " int main(void) { \n "
" const char *const outfile = \" out.txt \" ; \n "
" FILE *f; \n "
" f = fopen(outfile, \" w \" ); \n "
" fprintf(f, \" foo \\ n \" ), fclose(f); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void pointer_to_pointer ( ) {
2009-05-22 22:36:03 +02:00
check ( " void f(char **data) \n "
" { \n "
" char *c = new char[12]; \n "
" *c = 0; \n "
" *data = c; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
2014-11-20 14:20:09 +01:00
void dealloc_and_alloc_in_func ( ) {
2009-05-27 21:16:54 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
2014-11-20 14:20:09 +01:00
void unknownSyntax1 ( ) {
2009-07-31 23:42:21 +02:00
// 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-31 23:42:21 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-10-01 10:56:59 +02:00
2014-11-20 14:20:09 +01:00
void knownFunctions ( ) {
2009-10-01 10:56:59 +02:00
check ( " void foo() \n "
" { \n "
" int *p = new int[100]; \n "
" typeid(p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2009-10-01 10:56:59 +02:00
}
2009-10-12 21:36:28 +02:00
2014-11-20 14:20:09 +01:00
void same_function_name ( ) {
2009-10-12 21:36:28 +02:00
check ( " void a(char *p) \n "
" { } \n "
" void b() \n "
" { \n "
" char *p = malloc(10); \n "
" abc.a(p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-10-12 21:36:28 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-04-24 22:24:03 +02:00
2014-11-20 14:20:09 +01:00
void functionParameter ( ) {
2010-04-24 22:24:03 +02:00
check ( " void a(char *p) \n "
" { \n "
" p = malloc(100); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2010-04-24 22:24:03 +02:00
}
2010-09-03 07:18:01 +02:00
// Ticket #2014 - setjmp / longjmp
2014-11-20 14:20:09 +01:00
void jmp ( ) {
2010-09-03 07:18:01 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-09-03 07:18:01 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-09-27 12:25:34 +02:00
2014-11-20 14:20:09 +01:00
void trac1949 ( ) {
2012-07-16 14:02:33 +02:00
check ( " int fn() \n "
2010-09-27 12:25:34 +02:00
" { \n "
2012-07-16 14:02:33 +02:00
" char * buff = new char[100]; \n "
" assert (buff); \n "
" return 0; \n "
" } "
2010-09-27 12:25:34 +02:00
) ;
2015-08-16 01:21:11 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: buff \n " , errout . str ( ) ) ;
2010-09-27 12:25:34 +02:00
}
2011-03-20 09:16:52 +01:00
2014-11-20 14:20:09 +01:00
void trac2540 ( ) {
2012-04-26 13:16:46 +02:00
check ( " void f() \n "
" { \n "
" char* str = strdup( \" abc def \" ); \n "
" char *name = strtok(str, \" \" ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-04-26 13:16:46 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: str \n " , errout . str ( ) ) ;
check ( " void f(char *cBuf) \n "
" { \n "
" char* str = strdup(*cBuf); \n "
" char *name = strtok(str, \" \" ); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-04-26 13:16:46 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: str \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void trac2662 ( ) {
2011-03-20 09:16:52 +01:00
// segfault because of endless recursion
// call_func -> getAllocationType -> functionReturnType -> call_func ..
check ( " char *foo() { \n "
" return foo(); \n "
" } \n "
" \n "
" void bar() { \n "
" char *s = foo(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-20 09:16:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " char *foo() { \n "
" char *s = foo(); \n "
" return s; \n "
" } \n "
" \n "
" void bar() { \n "
" char *s = foo(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-20 09:16:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-23 18:45:47 +01:00
check ( " int shl() \n "
" { \n "
" int a = shr(); \n "
" return a; \n "
" } \n "
" \n "
" int shr() \n "
" { \n "
" return shl(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-03-23 18:45:47 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-03-20 09:16:52 +01:00
}
2011-10-25 22:38:23 +02:00
2014-11-20 14:20:09 +01:00
void trac1879 ( ) {
2011-10-25 22:38:23 +02:00
// #1879 non regression test case
check ( " void test() { \n "
" int *a = new int[10]; \n "
" try {} \n "
" catch(...) {} \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-30 19:43:02 +01:00
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2011-10-25 22:38:23 +02:00
}
2014-11-20 14:20:09 +01:00
void ptrptr ( ) {
2012-08-26 11:39:17 +02:00
check ( " void f() { \n "
" char *p; \n "
" char **pp = &p; \n "
2015-11-19 17:33:52 +01:00
" *pp = calloc(10, 1); \n "
2012-08-26 11:39:17 +02:00
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2015-01-30 20:55:53 +01:00
void c_code ( ) {
check ( " int main(void) { \n "
" struct llist *ll = malloc(sizeof(struct llist)); \n "
" free(ll); \n "
" ll = NULL; \n "
" delete(ll, ll->top); \n "
2015-10-07 18:33:57 +02:00
" } " , true ) ;
2015-01-30 20:55:53 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-01-11 10:12:39 +01:00
void gnucfg ( ) {
Settings settings ;
LOAD_LIB_2 ( settings . library , " gnu.cfg " ) ;
const char code [ ] = " void leak() { \n "
" char * p = get_current_dir_name(); \n " // memory leak
" } \n "
" void noLeak() { \n "
2015-01-11 10:27:37 +01:00
" char * p = get_current_dir_name(); \n "
2015-01-11 10:12:39 +01:00
" free(p) \n ; "
" } " ;
2015-10-07 18:33:57 +02:00
check ( code , false , true , false , & settings ) ;
2015-01-11 10:12:39 +01:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2015-07-25 18:50:27 +02:00
void trac3991 ( ) {
check ( " int read_chunk_data(char **buffer) { \n "
" *buffer = (char *)malloc(chunk->size); \n "
" if (*buffer == NULL) \n "
" return -1; \n "
" return 0; \n "
" } \n "
" void printf_chunk_recursive() { \n "
" UINT8 *data = NULL; \n "
" int avierr = read_chunk_data(&data); \n "
" if (avierr == 0) \n "
" free(data); \n "
2015-10-07 18:33:57 +02:00
" } " , true ) ;
2015-07-25 18:50:27 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-11-27 11:18:40 +01:00
void crash ( ) {
check ( " class ComponentDC { \n "
" ::Component * getComponent(); \n "
" }; \n "
" ::Component * ComponentDC::getComponent() { \n "
" return ((::Component *)myComponent); \n "
" } \n "
" class MultiComponentDC : public ComponentDC { \n "
" virtual void addChild(InterfaceNode *); \n "
" }; \n "
" void MultiComponentDC::addChild(InterfaceNode *childNode) { \n "
" ComponentDC *cdc = dynamic_cast<ComponentDC *>(childNode); \n "
" if (cdc) \n "
" ::Component *c = cdc->getComponent(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2016-09-10 14:54:43 +02:00
void trac7680 ( ) {
check ( " void foo() { \n "
" int *i = ::new int; \n "
" ::delete i; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2017-01-27 22:53:24 +01:00
void trac7440 ( ) {
check ( " int main(void) { \n "
" char* data = new char[100]; \n "
" char** dataPtr = &data; \n "
" printf( \" test \" ); \n "
" delete [] *dataPtr; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2008-12-18 22:28:57 +01:00
} ;
2015-10-07 14:30:01 +02:00
REGISTER_TEST ( TestMemleakInFunction )
2009-06-08 20:20:43 +02:00
2011-10-13 20:53:06 +02:00
class TestMemleakInClass : public TestFixture {
2009-06-08 20:20:43 +02:00
public :
2014-11-20 14:20:09 +01:00
TestMemleakInClass ( ) : TestFixture ( " TestMemleakInClass " ) {
2013-08-07 16:27:37 +02:00
}
2009-06-08 20:20:43 +02:00
private :
2015-10-07 18:33:57 +02:00
Settings settings ;
2010-04-18 21:14:25 +02:00
/**
* Tokenize and execute leak check for given code
* @ param code Source code
*/
2014-11-20 14:20:09 +01:00
void check ( const char code [ ] ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
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 " ) ;
2013-12-30 17:45:28 +01:00
tokenizer . simplifyTokenList2 ( ) ;
2009-06-08 20:20:43 +02:00
// Check for memory leaks..
CheckMemoryLeakInClass checkMemoryLeak ( & tokenizer , & settings , this ) ;
checkMemoryLeak . check ( ) ;
}
2018-05-15 16:37:40 +02:00
void run ( ) override {
2015-10-07 18:33:57 +02:00
settings . addEnabled ( " warning " ) ;
settings . addEnabled ( " style " ) ;
2015-11-19 17:33:52 +01:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
2009-06-08 20:20:43 +02:00
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
2010-12-07 07:08:05 +01:00
TEST_CASE ( class20 ) ;
2011-01-30 08:38:20 +01:00
TEST_CASE ( class21 ) ; // ticket #2517
2011-08-16 20:39:17 +02:00
TEST_CASE ( class22 ) ; // ticket #3012
2011-11-28 20:08:29 +01:00
TEST_CASE ( class23 ) ; // ticket #3303
2012-05-29 21:13:34 +02:00
TEST_CASE ( class24 ) ; // ticket #3806 - false positive in copy constructor
2013-02-24 08:14:25 +01:00
TEST_CASE ( class25 ) ; // ticket #4367 - false positive implementation for destructor is not seen
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 ) ;
2014-04-10 16:11:11 +02:00
TEST_CASE ( mismatch2 ) ; // #5659
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
}
2014-11-20 14:20:09 +01:00
void class1 ( ) {
2009-06-08 20:20:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Class 'Fred' is unsafe, 'Fred::str1' can leak by wrong usage. \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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Class 'Fred' is unsafe, 'Fred::str1' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
}
2009-06-08 20:20:43 +02:00
2014-11-20 14:20:09 +01:00
void class2 ( ) {
2009-06-08 20:20:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " [test.cpp:12]: (error) Mismatching allocation and deallocation: Fred::str1 \n " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2014-11-20 14:20:09 +01:00
void class3 ( ) {
2009-06-08 20:20:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2014-11-20 14:20:09 +01:00
void class4 ( ) {
2009-06-08 20:20:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-06-08 20:20:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2014-11-20 14:20:09 +01:00
void class6 ( ) {
2009-06-08 20:20:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
" void foo() \n "
2012-12-06 19:19:22 +01:00
" { \n "
2010-12-05 20:26:52 +01:00
" char *str = new char[100]; \n "
" delete [] str; \n "
" hello(); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2014-11-20 14:20:09 +01:00
void class7 ( ) {
2009-06-08 20:20:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2014-11-20 14:20:09 +01:00
void class8 ( ) {
2009-06-08 20:20:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
" void a() \n "
" { \n "
" int* c = new int(1); \n "
" delete c; \n "
" doNothing(c); \n "
" } \n "
" void doNothing() { } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2014-11-20 14:20:09 +01:00
void class9 ( ) {
2009-06-08 20:20:43 +02:00
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 "
2013-03-20 15:36:16 +01:00
" { delete (p); } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" { p = new int; } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
2009-06-08 20:20:43 +02:00
check ( " class A \n "
" { \n "
" public: \n "
" int * p; \n "
" A() { p = new int; } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2014-11-20 14:20:09 +01: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 "
" { } "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
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
" { } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2009-06-08 20:20:43 +02:00
}
2014-11-20 14:20:09 +01:00
void class12 ( ) {
2009-10-22 21:51:58 +02:00
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 "
2013-03-20 15:36:16 +01:00
" { delete [] p; } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:4]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2009-10-22 21:51:58 +02:00
}
2014-11-20 14:20:09 +01:00
void class13 ( ) {
2009-10-23 20:04:47 +02:00
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 "
2013-03-20 15:36:16 +01:00
" { p = new int[10]; delete [] p; } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
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
}
2014-11-20 14:20:09 +01:00
void class14 ( ) {
2010-01-27 22:05:04 +01:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init(); \n "
" }; \n "
" \n "
" void A::init() \n "
2013-03-20 15:36:16 +01:00
" { p = new int[10]; } " ) ;
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 "
2012-09-10 17:27:41 +02:00
" [test.cpp:3]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init() \n "
" { p = new int[10]; } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n "
2012-09-10 17:27:41 +02:00
" [test.cpp:3]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
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 "
2013-03-20 15:36:16 +01:00
" { p = new int; } " ) ;
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 "
2012-09-10 17:27:41 +02:00
" [test.cpp:3]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init() \n "
" { p = new int; } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n "
2012-09-10 17:27:41 +02:00
" [test.cpp:3]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
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 "
2013-03-20 15:36:16 +01:00
" { p = malloc(sizeof(int)*10); } " ) ;
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 "
2012-09-10 17:27:41 +02:00
" [test.cpp:3]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A \n "
" { \n "
" int *p; \n "
" public: \n "
" void init() \n "
" { p = malloc(sizeof(int)*10); } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " [test.cpp:6]: (warning) Possible leak in public function. The pointer 'p' is not deallocated before it is allocated. \n "
2012-09-10 17:27:41 +02:00
" [test.cpp:3]: (style) Class 'A' is unsafe, 'A::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-01-27 22:05:04 +01:00
}
2014-11-20 14:20:09 +01:00
void class15 ( ) {
2010-03-19 16:57:23 +01:00
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-03-19 16:57:23 +01:00
}
2014-11-20 14:20:09 +01:00
void class16 ( ) {
2010-06-12 13:37:44 +02:00
// 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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-06-12 13:37:44 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-06-08 20:20:43 +02:00
2014-11-20 14:20:09 +01:00
void class17 ( ) {
2010-06-13 10:43:23 +02:00
// 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2015-08-16 14:22:46 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (warning) Possible leak in public function. The pointer 'pd' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
check ( " class A { \n "
" private: \n "
" char *pd; \n "
" public: \n "
" void foo() \n "
" { \n "
" pd = new char[12]; \n "
" delete [] pd; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2015-08-16 14:22:46 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (warning) Possible leak in public function. The pointer 'pd' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
2010-12-05 20:26:52 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2015-08-16 14:22:46 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (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
}
2014-11-20 14:20:09 +01:00
void class18 ( ) {
2010-06-16 19:28:47 +02:00
// 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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2010-06-16 19:28:47 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-12-05 20:26:52 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-06-16 19:28:47 +02:00
}
2014-11-20 14:20:09 +01:00
void class19 ( ) {
2010-11-23 18:41:07 +01:00
// 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-11-23 18:41:07 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Class 'Foo' is unsafe, 'Foo::rp1' can leak by wrong usage. \n "
" [test.cpp:6]: (style) Class 'Foo' is unsafe, 'Foo::rp2' can leak by wrong usage. \n " , 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 "
" ~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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-12-04 07:29:12 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-12-07 07:08:05 +01:00
}
2014-11-20 14:20:09 +01:00
void class20 ( ) {
2010-12-07 07:08:05 +01:00
check ( " namespace ns1 { \n "
" 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Class 'Fred' is unsafe, 'Fred::str1' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-07 07:08:05 +01:00
check ( " namespace ns1 { \n "
" 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 "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Class 'Fred' is unsafe, 'Fred::str1' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-07 07:08:05 +01:00
check ( " namespace ns1 { \n "
" class Fred \n "
" { \n "
" private: \n "
" char *str1; \n "
" char *str2; \n "
" public: \n "
" Fred(); \n "
" ~Fred(); \n "
" }; \n "
" } \n "
" ns1::Fred::Fred() \n "
" { \n "
" str1 = new char[10]; \n "
" str2 = new char[10]; \n "
" } \n "
" \n "
" ns1::Fred::~Fred() \n "
" { \n "
" delete [] str2; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:5]: (style) Class 'Fred' is unsafe, 'Fred::str1' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-07 07:08:05 +01:00
check ( " namespace ns1 { \n "
" namespace ns2 { \n "
" class Fred \n "
" { \n "
" private: \n "
" char *str1; \n "
" char *str2; \n "
" public: \n "
" Fred(); \n "
" ~Fred(); \n "
" }; \n "
" } \n "
" } \n "
" ns1::ns2::Fred::Fred() \n "
" { \n "
" str1 = new char[10]; \n "
" str2 = new char[10]; \n "
" } \n "
" \n "
" ns1::ns2::Fred::~Fred() \n "
" { \n "
" delete [] str2; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:6]: (style) Class 'Fred' is unsafe, 'Fred::str1' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-12-07 07:08:05 +01:00
check ( " namespace ns1 { \n "
" namespace ns2 { \n "
" namespace ns3 { \n "
" class Fred \n "
" { \n "
" private: \n "
" char *str1; \n "
" char *str2; \n "
" public: \n "
" Fred(); \n "
" ~Fred(); \n "
" }; \n "
" } \n "
" } \n "
" } \n "
" ns1::ns2::ns3::Fred::Fred() \n "
" { \n "
" str1 = new char[10]; \n "
" str2 = new char[10]; \n "
" } \n "
" \n "
" ns1::ns2::ns3::Fred::~Fred() \n "
" { \n "
" delete [] str2; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (style) Class 'Fred' is unsafe, 'Fred::str1' can leak by wrong usage. \n " , errout . str ( ) ) ;
2010-11-23 18:41:07 +01:00
}
2014-11-20 14:20:09 +01:00
void class21 ( ) { // ticket #2517
2011-01-30 08:38:20 +01:00
check ( " struct B { }; \n "
" struct C \n "
" { \n "
" B * b; \n "
" C(B * x) : b(x) { } \n "
" }; \n "
" class A \n "
" { \n "
" B *b; \n "
" C *c; \n "
" public: \n "
" A() : b(new B()), c(new C(b)) { } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (style) Class 'A' is unsafe, 'A::b' can leak by wrong usage. \n "
" [test.cpp:10]: (style) Class 'A' is unsafe, 'A::c' can leak by wrong usage. \n " , errout . str ( ) ) ;
2011-01-30 08:38:20 +01:00
check ( " struct B { }; \n "
" struct C \n "
" { \n "
" B * b; \n "
" C(B * x) : b(x) { } \n "
" }; \n "
" class A \n "
" { \n "
" B *b; \n "
" C *c; \n "
" public: \n "
" A() \n "
" { \n "
" b = new B(); \n "
" c = new C(b); \n "
" } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-09-10 17:27:41 +02:00
ASSERT_EQUALS ( " [test.cpp:9]: (style) Class 'A' is unsafe, 'A::b' can leak by wrong usage. \n "
" [test.cpp:10]: (style) Class 'A' is unsafe, 'A::c' can leak by wrong usage. \n " , errout . str ( ) ) ;
2011-01-30 08:38:20 +01:00
}
2014-11-20 14:20:09 +01:00
void class22 ( ) { // ticket #3012 - false positive
2011-08-16 20:39:17 +02:00
check ( " class Fred { \n "
" private: \n "
" int * a; \n "
" private: \n "
" Fred() { a = new int; } \n "
" ~Fred() { (delete(a), (a)=NULL); } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2011-08-16 20:39:17 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void class23 ( ) { // ticket #3303 - false positive
2011-11-28 20:08:29 +01:00
check ( " class CDataImpl { \n "
" public: \n "
" CDataImpl() { m_refcount = 1; } \n "
" void Release() { if (--m_refcount == 0) delete this; } \n "
" private: \n "
" int m_refcount; \n "
" }; \n "
" \n "
" class CData { \n "
" public: \n "
" CData() : m_impl(new CDataImpl()) { } \n "
" ~CData() { if (m_impl) m_impl->Release(); } \n "
" private: \n "
" CDataImpl *m_impl; \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2011-11-28 20:08:29 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void class24 ( ) { // ticket #3806 - false positive in copy constructor
2012-05-29 21:13:34 +02:00
check ( " class Fred { \n "
" private: \n "
" int * a; \n "
" public: \n "
" Fred(const Fred &fred) { a = new int; } \n "
" ~Fred() { delete a; } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2012-05-29 21:13:34 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void class25 ( ) { // ticket #4367 - false positive when implementation for destructor is not seen
2013-02-24 08:14:25 +01:00
check ( " class Fred { \n "
" private: \n "
" int * a; \n "
" public: \n "
" Fred() { a = new int; } \n "
" ~Fred(); \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2013-02-24 08:14:25 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void staticvar ( ) {
2009-10-06 18:25:00 +02:00
check ( " class A \n "
" { \n "
" private: \n "
" static int * p; \n "
" public: "
" A() \n "
" { \n "
" if (!p) \n "
" p = new int[100]; \n "
" } \n "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2009-10-06 18:25:00 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
2014-11-20 14:20:09 +01:00
void mismatch1 ( ) {
2010-01-27 21:02:13 +01:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
}
2014-11-20 14:20:09 +01:00
void mismatch2 ( ) { // #5659
2014-04-10 16:11:11 +02:00
check ( " namespace NS \n "
" { \n "
" class Foo \n "
" { \n "
" public: \n "
" void fct(); \n "
" \n "
" private: \n "
" char* data_; \n "
" }; \n "
" } \n "
" \n "
" using namespace NS; \n "
" \n "
" void Foo::fct() \n "
" { \n "
" data_ = new char[42]; \n "
" delete data_; \n "
" data_ = 0; \n "
" } \n " ) ;
2015-08-16 14:22:46 +02:00
ASSERT_EQUALS ( " [test.cpp:17]: (warning) Possible leak in public function. The pointer 'data_' is not deallocated before it is allocated. \n "
2014-04-11 05:40:37 +02:00
" [test.cpp:18]: (error) Mismatching allocation and deallocation: Foo::data_ \n " , errout . str ( ) ) ;
check ( " namespace NS \n "
" { \n "
" class Foo \n "
" { \n "
" public: \n "
" void fct(int i); \n "
" \n "
" private: \n "
" char* data_; \n "
" }; \n "
" } \n "
" \n "
" using namespace NS; \n "
" \n "
" void Foo::fct(int i) \n "
" { \n "
" data_ = new char[42]; \n "
" delete data_; \n "
" data_ = 0; \n "
" } \n " ) ;
2015-08-16 14:22:46 +02:00
ASSERT_EQUALS ( " [test.cpp:17]: (warning) Possible leak in public function. The pointer 'data_' is not deallocated before it is allocated. \n "
2014-04-10 16:11:11 +02:00
" [test.cpp:18]: (error) Mismatching allocation and deallocation: Foo::data_ \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void func1 ( ) {
2010-05-15 19:40:32 +02:00
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
2011-03-19 09:04:03 +01:00
ASSERT_EQUALS ( " [test.cpp:7]: (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
}
2014-11-20 14:20:09 +01:00
void func2 ( ) {
2010-05-15 19:40:32 +02:00
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 "
2013-03-20 15:36:16 +01:00
" }; " ) ;
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
2015-10-07 14:30:01 +02:00
REGISTER_TEST ( TestMemleakInClass )
2008-12-18 22:28:57 +01:00
2009-06-16 22:01:04 +02:00
2011-10-13 20:53:06 +02:00
class TestMemleakStructMember : public TestFixture {
2009-06-16 22:01:04 +02:00
public :
2014-11-20 14:20:09 +01:00
TestMemleakStructMember ( ) : TestFixture ( " TestMemleakStructMember " ) {
2013-08-07 16:27:37 +02:00
}
2009-06-16 22:01:04 +02:00
private :
2015-10-07 18:33:57 +02:00
Settings settings ;
2016-01-31 10:08:00 +01:00
void check ( const char code [ ] , bool isCPP = true ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
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 ) ;
2016-01-31 10:08:00 +01:00
tokenizer . tokenize ( istr , isCPP ? " test.cpp " : " test.c " ) ;
2013-12-30 17:45:28 +01:00
tokenizer . simplifyTokenList2 ( ) ;
2009-06-16 22:01:04 +02:00
// Check for memory leaks..
CheckMemoryLeakStructMember checkMemoryLeakStructMember ( & tokenizer , & settings , this ) ;
checkMemoryLeakStructMember . check ( ) ;
}
2018-05-15 16:37:40 +02:00
void run ( ) override {
2015-11-19 17:33:52 +01:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
LOAD_LIB_2 ( settings . library , " posix.cfg " ) ;
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
2011-01-22 13:40:19 +01:00
TEST_CASE ( ret1 ) ;
TEST_CASE ( ret2 ) ;
2009-07-19 16:51:31 +02:00
// assignments
2011-02-04 20:41:35 +01:00
TEST_CASE ( assign1 ) ;
TEST_CASE ( assign2 ) ;
2011-08-08 19:58:25 +02:00
TEST_CASE ( assign3 ) ;
2009-07-19 16:51:31 +02:00
// Failed allocation
TEST_CASE ( failedAllocation ) ;
2009-07-22 08:30:51 +02:00
2011-07-21 13:33:20 +02:00
TEST_CASE ( function1 ) ; // Deallocating in function
TEST_CASE ( function2 ) ; // #2848: Taking address in function
2011-08-20 09:17:34 +02:00
TEST_CASE ( function3 ) ; // #3024: kernel list
2011-08-26 19:26:21 +02:00
TEST_CASE ( function4 ) ; // #3038: Deallocating in function
2009-07-23 22:29:31 +02:00
// Handle if-else
TEST_CASE ( ifelse ) ;
2009-09-28 22:58:06 +02:00
2012-06-23 20:15:58 +02:00
// Linked list
TEST_CASE ( linkedlist ) ;
2009-09-28 22:58:06 +02:00
// struct variable is a global variable
TEST_CASE ( globalvar ) ;
2011-05-11 18:19:14 +02:00
// local struct variable
2013-04-26 16:11:57 +02:00
TEST_CASE ( localvars ) ;
2013-09-21 18:10:29 +02:00
// Segmentation fault in CheckMemoryLeakStructMember
TEST_CASE ( trac5030 ) ;
2014-01-03 23:23:06 +01:00
TEST_CASE ( varid ) ; // #5201: Analysis confused by (variable).attribute notation
2014-05-08 20:51:18 +02:00
TEST_CASE ( varid_2 ) ; // #5315: Analysis confused by ((variable).attribute) notation
2015-11-19 16:10:00 +01:00
TEST_CASE ( customAllocation ) ;
2009-06-16 22:01:04 +02:00
}
2014-11-20 14:20:09 +01: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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-19 16:51:31 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-19 16:51:31 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-20 14:39:24 +02:00
ASSERT_EQUALS ( " [test.cpp:10]: (error) Memory leak: abc.a \n " , errout . str ( ) ) ;
2009-07-19 16:51:31 +02:00
}
2014-11-20 14:20:09 +01:00
void goto_ ( ) {
2009-07-19 16:51:31 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-09-28 22:41:45 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-19 16:51:31 +02:00
}
2014-11-20 14:20:09 +01:00
void ret1 ( ) {
2009-07-19 16:51:31 +02:00
check ( " static ABC * foo() \n "
" { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" return abc; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-19 16:51:31 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " static void foo(struct ABC *abc) \n "
" { \n "
" abc->a = malloc(10); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-19 16:51:31 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-01-31 10:08:00 +01:00
// #7302
check ( " void* foo() { \n "
" struct ABC abc; \n "
" abc.a = malloc(10); \n "
" return abc.a; \n "
" } " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void* foo() { \n "
" struct ABC abc; \n "
" abc.a = malloc(10); \n "
" return abc.b; \n "
" } " , false ) ;
ASSERT_EQUALS ( " [test.c:4]: (error) Memory leak: abc.a \n " , errout . str ( ) ) ;
2009-07-19 16:51:31 +02:00
}
2014-11-20 14:20:09 +01:00
void ret2 ( ) {
2011-01-22 13:40:19 +01:00
check ( " static ABC * foo() \n "
" { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" return &abc->self; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-22 13:40:19 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign1 ( ) {
2009-07-19 16:51:31 +02:00
check ( " static void foo() \n "
" { \n "
" struct ABC *abc = abc1; \n "
" abc->a = malloc(10); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-19 16:51:31 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-19 16:51:31 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-19 16:51:31 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign2 ( ) {
2011-02-04 20:41:35 +01:00
check ( " static void foo() { \n "
" struct ABC *abc = malloc(123); \n "
2011-08-08 19:58:25 +02:00
" abc->a = abc->b = malloc(10); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-02-04 20:41:35 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign3 ( ) {
2011-08-08 19:58:25 +02:00
check ( " void f(struct s *f1) { \n "
" struct s f2; \n "
" f2.a = malloc(100); \n "
" *f1 = f2; \n "
2016-02-02 09:18:58 +01:00
" } " , false ) ;
2014-02-02 00:10:26 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-08 19:58:25 +02:00
}
2014-11-20 14:20:09 +01:00
void failedAllocation ( ) {
2009-07-19 16:51:31 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-19 16:51:31 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-06-16 22:01:04 +02:00
}
2009-07-22 08:30:51 +02:00
2014-11-20 14:20:09 +01:00
void function1 ( ) {
2009-07-22 08:30:51 +02:00
// 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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-22 08:30:51 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-07-29 11:38:20 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-07-22 08:30:51 +02:00
}
2009-07-23 22:29:31 +02:00
2011-07-21 13:33:20 +02:00
// #2848: Taking address in function 'assign'
2014-11-20 14:20:09 +01:00
void function2 ( ) {
2011-07-21 13:33:20 +02:00
check ( " void f() { \n "
" A a = { 0 }; \n "
" a.foo = (char *) malloc(10); \n "
" assign(&a); \n "
2016-02-02 09:18:58 +01:00
" } " , false ) ;
2014-02-02 00:10:26 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-07-21 13:33:20 +02:00
}
2011-08-20 09:17:34 +02:00
// #3024: kernel list
2014-11-20 14:20:09 +01:00
void function3 ( ) {
2011-08-20 09:17:34 +02:00
check ( " void f() { \n "
2015-11-19 18:51:32 +01:00
" struct ABC *abc = malloc(100); \n "
" abc.a = (char *) malloc(10); \n "
2011-08-20 09:17:34 +02:00
" list_add_tail(&abc->list, head); \n "
2016-02-02 09:18:58 +01:00
" } " , false ) ;
2011-08-20 09:17:34 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-08-26 19:26:21 +02:00
// #3038: deallocating in function
2014-11-20 14:20:09 +01:00
void function4 ( ) {
2011-08-26 19:26:21 +02:00
check ( " void a(char *p) { char *x = p; free(x); } \n "
" void b() { \n "
" struct ABC abc; \n "
" abc.a = (char *) malloc(10); \n "
" a(abc.a); \n "
2016-02-02 09:18:58 +01:00
" } " , false ) ;
2014-02-02 00:10:26 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-08-26 19:26:21 +02:00
}
2014-11-20 14:20:09 +01:00
void ifelse ( ) {
2009-07-23 22:29:31 +02:00
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 "
2013-03-20 15:36:16 +01:00
" } " ) ;
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
2014-11-20 14:20:09 +01:00
void linkedlist ( ) {
2012-06-23 20:20:11 +02:00
// #3904 - false positive when linked list is used
2012-06-23 20:15:58 +02:00
check ( " static void foo() { \n "
" struct ABC *abc = malloc(sizeof(struct ABC)); \n "
" abc->next = malloc(sizeof(struct ABC)); \n "
" abc->next->next = NULL; \n "
" \n "
" while (abc) { \n "
" struct ABC *next = abc->next; \n "
" free(abc); \n "
" abc = next; \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void globalvar ( ) {
2009-09-28 22:58:06 +02:00
check ( " struct ABC *abc; \n "
" \n "
" static void foo() \n "
" { \n "
" abc = malloc(sizeof(struct ABC)); \n "
" abc->a = malloc(10); \n "
" return; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2009-09-28 22:58:06 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2011-05-11 18:19:14 +02:00
2013-04-26 16:11:57 +02:00
// Ticket #933 Leaks with struct members not detected
2014-11-20 14:20:09 +01:00
void localvars ( ) {
2013-04-30 06:44:50 +02:00
// Test error case
2015-11-19 16:10:00 +01:00
const char code1 [ ] = " struct A { \n "
" FILE* f; \n "
" char* c; \n "
" void* m; \n "
" }; \n "
" \n "
" void func() { \n "
" struct A a; \n "
" a.f = fopen( \" test \" , \" r \" ); \n "
" a.c = new char[12]; \n "
" a.m = malloc(12); \n "
" } " ;
2016-01-31 10:08:00 +01:00
check ( code1 , true ) ;
2015-11-19 16:10:00 +01:00
ASSERT_EQUALS ( " [test.cpp:12]: (error) Memory leak: a.f \n "
" [test.cpp:12]: (error) Memory leak: a.c \n "
" [test.cpp:12]: (error) Memory leak: a.m \n " , errout . str ( ) ) ;
2016-01-31 10:08:00 +01:00
check ( code1 , false ) ;
2013-04-26 16:11:57 +02:00
ASSERT_EQUALS ( " [test.c:12]: (error) Memory leak: a.f \n "
" [test.c:12]: (error) Memory leak: a.m \n " , errout . str ( ) ) ;
// Test OK case
2015-11-19 16:10:00 +01:00
const char code2 [ ] = " struct A { \n "
" FILE* f; \n "
" char* c; \n "
" void* m; \n "
" }; \n "
" \n "
" void func() { \n "
" struct A a; \n "
" a.f = fopen( \" test \" , \" r \" ); \n "
" a.c = new char[12]; \n "
" a.m = malloc(12); \n "
" fclose(a.f); \n "
" delete [] a.c; \n "
" free(a.m); \n "
" } " ;
2016-01-31 10:08:00 +01:00
check ( code2 , true ) ;
2015-11-19 16:10:00 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-01-31 10:08:00 +01:00
check ( code2 , false ) ;
2015-11-19 16:10:00 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// Test unknown struct. In C++, it might have a destructor
const char code3 [ ] = " void func() { \n "
" struct A a; \n "
" a.f = fopen( \" test \" , \" r \" ); \n "
" } " ;
2016-01-31 10:08:00 +01:00
check ( code3 , true ) ;
2015-11-19 16:10:00 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-01-31 10:08:00 +01:00
check ( code3 , false ) ;
2015-11-19 16:10:00 +01:00
ASSERT_EQUALS ( " [test.c:4]: (error) Memory leak: a.f \n " , errout . str ( ) ) ;
// Test struct with destructor
const char code4 [ ] = " struct A { \n "
" FILE* f; \n "
" ~A(); \n "
" }; \n "
" void func() { \n "
" struct A a; \n "
" a.f = fopen( \" test \" , \" r \" ); \n "
" } " ;
2016-01-31 10:08:00 +01:00
check ( code4 , true ) ;
2014-02-02 00:10:26 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-05-11 18:19:14 +02:00
}
2013-09-21 18:10:29 +02:00
// don't crash
2014-11-20 14:20:09 +01:00
void trac5030 ( ) {
2013-09-21 18:10:29 +02:00
check ( " bool bob( char const **column_ptrs ) { \n "
" unique_ptr<char[]>otherbuffer{new char[otherbufsize+1]}; \n "
" char *const oldbuffer = otherbuffer.get(); \n "
" int const oldbufsize = otherbufsize; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-01-03 23:23:06 +01:00
2014-11-20 14:20:09 +01:00
void varid ( ) { // #5201
2014-01-03 23:23:06 +01:00
check ( " struct S { \n "
" void *state_check_buff; \n "
" }; \n "
" void f() { \n "
" S s; \n "
" (s).state_check_buff = (void* )malloc(1); \n "
" if (s.state_check_buff == 0) \n "
" return; \n "
2016-01-31 10:08:00 +01:00
" } " , false ) ;
2014-01-03 23:23:06 +01:00
ASSERT_EQUALS ( " [test.c:9]: (error) Memory leak: s.state_check_buff \n " , errout . str ( ) ) ;
}
2014-05-08 20:51:18 +02:00
2014-11-20 14:20:09 +01:00
void varid_2 ( ) { // #5315
2014-05-08 20:51:18 +02:00
check ( " typedef struct foo { char *realm; } foo; \n "
" void build_principal() { \n "
" foo f; \n "
" ((f)->realm) = strdup(realm); \n "
" if(f->realm == NULL) {} \n "
2016-01-31 10:08:00 +01:00
" } " , false ) ;
2014-05-08 20:51:18 +02:00
ASSERT_EQUALS ( " [test.c:6]: (error) Memory leak: f.realm \n " , errout . str ( ) ) ;
}
2015-11-19 16:10:00 +01:00
void customAllocation ( ) { // #4770
check ( " char *myalloc(void) { \n "
" return malloc(100); \n "
" } \n "
" void func() { \n "
" struct ABC abc; \n "
" abc.a = myalloc(); \n "
2016-01-31 10:08:00 +01:00
" } " , false ) ;
2015-11-19 16:10:00 +01:00
ASSERT_EQUALS ( " [test.c:7]: (error) Memory leak: abc.a \n " , errout . str ( ) ) ;
}
2009-06-16 22:01:04 +02:00
} ;
2015-10-07 14:30:01 +02:00
REGISTER_TEST ( TestMemleakStructMember )
2009-06-16 22:01:04 +02:00
2010-11-12 21:09:34 +01:00
2011-10-13 20:53:06 +02:00
class TestMemleakNoVar : public TestFixture {
2010-11-12 21:09:34 +01:00
public :
2014-11-20 14:20:09 +01:00
TestMemleakNoVar ( ) : TestFixture ( " TestMemleakNoVar " ) {
2013-08-07 16:27:37 +02:00
}
2010-11-12 21:09:34 +01:00
private :
2014-03-24 09:59:05 +01:00
Settings settings ;
2014-11-20 14:20:09 +01:00
void check ( const char code [ ] ) {
2010-12-01 18:00:55 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2014-03-24 09:59:05 +01:00
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
tokenizer . tokenize ( istr , " test.cpp " ) ;
tokenizer . simplifyTokenList2 ( ) ;
// Check for memory leaks..
CheckMemoryLeakNoVar checkMemoryLeakNoVar ( & tokenizer , & settings , this ) ;
checkMemoryLeakNoVar . check ( ) ;
}
2018-05-15 16:37:40 +02:00
void run ( ) override {
2015-01-04 11:07:53 +01:00
settings . inconclusive = true ;
2015-06-19 23:44:43 +02:00
settings . standards . posix = true ;
2015-01-04 11:07:53 +01:00
settings . addEnabled ( " warning " ) ;
2010-12-01 18:00:55 +01:00
2015-11-18 22:09:27 +01:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
2015-11-19 17:33:52 +01:00
LOAD_LIB_2 ( settings . library , " posix.cfg " ) ;
2014-02-05 08:18:39 +01:00
2010-11-12 21:09:34 +01:00
// pass allocated memory to function..
TEST_CASE ( functionParameter ) ;
2015-01-04 11:07:53 +01:00
2012-03-14 23:45:20 +01:00
// never use leakable resource
2014-01-03 10:12:32 +01:00
TEST_CASE ( missingAssignment ) ;
2015-01-04 11:07:53 +01:00
// pass allocated memory to function using a smart pointer
TEST_CASE ( smartPointerFunctionParam ) ;
2018-04-05 06:47:59 +02:00
TEST_CASE ( resourceLeak ) ;
2010-11-12 21:09:34 +01:00
}
2014-11-20 14:20:09 +01:00
void functionParameter ( ) {
2010-11-12 21:09:34 +01:00
// standard function..
check ( " void x() { \n "
" strcpy(a, strdup(p)); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2010-11-12 21:09:34 +01:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Allocation with strdup, strcpy doesn't release it. \n " , errout . str ( ) ) ;
2011-11-11 09:07:02 +01:00
check ( " char *x() { \n "
" char *ret = strcpy(malloc(10), \" abc \" ); \n "
" return ret; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-11 09:07:02 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-01-02 08:32:51 +01:00
check ( " void x() { \n "
" free(malloc(10)); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-01-02 08:32:51 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2010-11-12 21:09:34 +01:00
// user function..
check ( " void set_error(const char *msg) { \n "
" } \n "
" \n "
" void x() { \n "
" set_error(strdup(p)); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2015-07-24 08:30:38 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:5]: (error) Allocation with strdup, set_error doesn't release it. \n " , " " , errout . str ( ) ) ;
2011-11-07 22:50:57 +01:00
check ( " void f() \n "
" { \n "
" int fd; \n "
" fd = mkstemp(strdup( \" /tmp/file.XXXXXXXX \" )); \n "
" close(fd); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2011-11-11 09:07:02 +01:00
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Allocation with strdup, mkstemp doesn't release it. \n " , " " , errout . str ( ) ) ;
2014-01-28 14:30:36 +01:00
check ( " void f() \n "
" { \n "
" if(TRUE || strcmp(strdup(a), b)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Allocation with strdup, strcmp doesn't release it. \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" if(!strcmp(strdup(a), b) == 0); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Allocation with strdup, strcmp doesn't release it. \n " , errout . str ( ) ) ;
2014-02-05 18:49:34 +01:00
2014-01-28 14:30:36 +01:00
check ( " void f() \n "
" { \n "
" 42, strcmp(strdup(a), b); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Allocation with strdup, strcmp doesn't release it. \n " , errout . str ( ) ) ;
2010-11-12 21:09:34 +01:00
}
2012-03-14 23:45:20 +01:00
2014-11-20 14:20:09 +01:00
void missingAssignment ( ) {
2012-03-14 23:45:20 +01:00
check ( " void x() \n "
" { \n "
" malloc(10); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2015-07-31 13:52:21 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Return value of allocation function 'malloc' is not stored. \n " , errout . str ( ) ) ;
2014-01-03 10:12:32 +01:00
check ( " void x() \n "
" { \n "
2015-11-19 17:33:52 +01:00
" calloc(10, 1); \n "
2014-01-03 10:12:32 +01:00
" } " ) ;
2015-07-31 13:52:21 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Return value of allocation function 'calloc' is not stored. \n " , errout . str ( ) ) ;
2014-01-03 10:12:32 +01:00
check ( " void x() \n "
" { \n "
" strdup( \" Test \" ); \n "
" } " ) ;
2015-07-31 13:52:21 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Return value of allocation function 'strdup' is not stored. \n " , errout . str ( ) ) ;
2014-01-03 10:12:32 +01:00
check ( " void x() \n "
" { \n "
" (char*) malloc(10); \n "
" } " ) ;
2015-07-31 13:52:21 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Return value of allocation function 'malloc' is not stored. \n " , errout . str ( ) ) ;
2014-01-03 10:12:32 +01:00
check ( " void x() \n "
" { \n "
" char* ptr = malloc(10); \n "
" foo(ptr); \n "
" free(ptr); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-05-21 13:45:36 +02:00
check ( " char** x(const char* str) { \n "
" char* ptr[] = { malloc(10), malloc(5), strdup(str) }; \n "
" return ptr; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-01-03 10:12:32 +01:00
check ( " void x() \n "
" { \n "
" 42,malloc(42); \n "
" } " ) ;
2015-07-31 13:52:21 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Return value of allocation function 'malloc' is not stored. \n " , errout . str ( ) ) ;
2012-03-14 23:45:20 +01:00
check ( " void *f() \n "
" { \n "
" return malloc(10); \n "
" } \n "
" void x() \n "
" { \n "
" f(); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2015-07-31 13:52:21 +02:00
ASSERT_EQUALS ( " [test.cpp:7]: (error) Return value of allocation function 'f' is not stored. \n " , errout . str ( ) ) ;
2015-01-31 17:27:43 +01:00
check ( " void x() \n "
" { \n "
" if(!malloc(5)) fail(); \n "
" } " ) ;
2015-07-31 13:52:21 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Return value of allocation function 'malloc' is not stored. \n " , errout . str ( ) ) ;
2015-01-31 20:34:06 +01:00
check ( " FOO* factory() { \n "
" FOO* foo = new (std::nothrow) FOO; \n "
" return foo; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-06-19 23:44:43 +02:00
// Ticket #6536
check ( " struct S { S(int) {} }; \n "
" void foo(int i) { \n "
" S socket(i); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-11-10 14:19:25 +01:00
// Ticket #6693
check ( " struct CTest { \n "
" void Initialise(); \n "
" void malloc(); \n "
" }; \n "
" void CTest::Initialise() { \n "
" malloc(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-12-05 18:43:29 +01:00
2016-01-25 10:33:11 +01:00
check ( " void foo() { \n " // #7348 - cast
" p = (::X*)malloc(42); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-12-05 18:43:29 +01:00
// #7182 "crash: CheckMemoryLeak::functionReturnType()"
check ( " template<typename... Ts> auto unary_right_comma (Ts... ts) { return (ts , ...); } \n "
" template<typename T, typename... Ts> auto binary_left_comma (T x, Ts... ts) { return (x , ... , ts); } \n "
" int main() { \n "
" unary_right_comma (a); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-03-14 23:45:20 +01:00
}
2015-01-04 11:07:53 +01:00
void smartPointerFunctionParam ( ) {
check ( " void x() { \n "
" f(shared_ptr<int>(new int(42)), g()); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning, inconclusive) Unsafe allocation. If g() throws, memory could be leaked. Use make_shared<int>() instead. \n " , errout . str ( ) ) ;
check ( " void x() { \n "
" h(12, f(shared_ptr<int>(new int(42)), g())); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning, inconclusive) Unsafe allocation. If g() throws, memory could be leaked. Use make_shared<int>() instead. \n " , errout . str ( ) ) ;
check ( " void x() { \n "
" f(unique_ptr<int>(new int(42)), g()); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning, inconclusive) Unsafe allocation. If g() throws, memory could be leaked. Use make_unique<int>() instead. \n " , errout . str ( ) ) ;
check ( " void x() { \n "
" f(g(), shared_ptr<int>(new int(42))); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning, inconclusive) Unsafe allocation. If g() throws, memory could be leaked. Use make_shared<int>() instead. \n " , errout . str ( ) ) ;
check ( " void x() { \n "
" f(g(), unique_ptr<int>(new int(42))); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning, inconclusive) Unsafe allocation. If g() throws, memory could be leaked. Use make_unique<int>() instead. \n " , errout . str ( ) ) ;
check ( " void x() { \n "
" f(shared_ptr<char>(new char), make_unique<int>(32)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning, inconclusive) Unsafe allocation. If make_unique<int>() throws, memory could be leaked. Use make_shared<char>() instead. \n " , errout . str ( ) ) ;
check ( " void x() { \n "
" f(g(124), h( \" test \" , 234), shared_ptr<char>(new char)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning, inconclusive) Unsafe allocation. If h() throws, memory could be leaked. Use make_shared<char>() instead. \n " , errout . str ( ) ) ;
2015-11-19 15:29:15 +01:00
check ( " void x() { \n "
" f(shared_ptr<std::string>(new std::string( \" \" )), g<std::string>()); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (warning, inconclusive) Unsafe allocation. If g<std::string>() throws, memory could be leaked. Use make_shared<std::string>() instead. \n " , errout . str ( ) ) ;
2015-01-04 11:07:53 +01:00
check ( " void g(int x) throw() { } \n "
" void x() { \n "
" f(g(124), shared_ptr<char>(new char)); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void __declspec(nothrow) g(int x) { } \n "
" void x() { \n "
" f(g(124), shared_ptr<char>(new char)); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-04-05 06:47:59 +02:00
void resourceLeak ( ) {
check ( " void foo() { \n "
" fopen( \" file.txt \" , \" r \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Return value of allocation function 'fopen' is not stored. \n " , errout . str ( ) ) ;
check ( " struct Holder { \n "
" Holder(FILE* f) : file(f) {} \n "
" ~Holder() { fclose(file); } \n "
" FILE* file; \n "
" }; \n "
" void foo() { \n "
" Holder h ( fopen( \" file.txt \" , \" r \" )); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Holder { \n "
" Holder(FILE* f) : file(f) {} \n "
" ~Holder() { fclose(file); } \n "
" FILE* file; \n "
" }; \n "
" void foo() { \n "
" Holder ( fopen( \" file.txt \" , \" r \" )); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Holder { \n "
" Holder(FILE* f) : file(f) {} \n "
" ~Holder() { fclose(file); } \n "
" FILE* file; \n "
" }; \n "
" void foo() { \n "
" Holder h { fopen( \" file.txt \" , \" r \" )}; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Holder { \n "
" Holder(FILE* f) : file(f) {} \n "
" ~Holder() { fclose(file); } \n "
" FILE* file; \n "
" }; \n "
" void foo() { \n "
" Holder h = fopen( \" file.txt \" , \" r \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Holder { \n "
" Holder(FILE* f) : file(f) {} \n "
" ~Holder() { fclose(file); } \n "
" FILE* file; \n "
" }; \n "
" void foo() { \n "
" Holder { fopen( \" file.txt \" , \" r \" )}; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Holder { \n "
" Holder(int i, FILE* f) : file(f) {} \n "
" ~Holder() { fclose(file); } \n "
" FILE* file; \n "
" }; \n "
" void foo() { \n "
" Holder { 0, fopen( \" file.txt \" , \" r \" )}; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2010-11-12 21:09:34 +01:00
} ;
2013-06-30 19:44:12 +02:00
REGISTER_TEST ( TestMemleakNoVar )
2014-02-06 09:22:07 +01:00
class TestMemleakGLib : public TestFixture {
public :
2014-11-20 14:20:09 +01:00
TestMemleakGLib ( ) : TestFixture ( " TestMemleakGLib " ) {
2014-02-06 09:22:07 +01:00
}
private :
2014-03-24 09:59:05 +01:00
Settings settings ;
2014-11-20 14:20:09 +01:00
void check ( const char code [ ] ) {
2014-02-06 09:22:07 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
2017-05-18 21:52:31 +02:00
std : : istringstream istr ( code ) ;
2018-04-09 09:41:24 +02:00
std : : vector < std : : string > files ( 1 , " test.cpp " ) ;
2017-05-18 21:52:31 +02:00
const simplecpp : : TokenList tokens1 ( istr , files , files [ 0 ] ) ;
2014-02-06 09:22:07 +01:00
// Preprocess...
2015-07-24 13:30:41 +02:00
Preprocessor preprocessor ( settings , this ) ;
2017-05-18 21:52:31 +02:00
const simplecpp : : TokenList & tokens2 = preprocessor . preprocess ( tokens1 , " " , files ) ;
2014-02-06 09:22:07 +01:00
2017-05-18 21:52:31 +02:00
// Tokenizer..
2014-02-06 09:22:07 +01:00
Tokenizer tokenizer ( & settings , this ) ;
2017-05-18 21:52:31 +02:00
tokenizer . createTokens ( & tokens2 ) ;
tokenizer . simplifyTokenList1 ( files [ 0 ] . c_str ( ) ) ;
2014-02-06 09:22:07 +01:00
tokenizer . simplifyTokenList2 ( ) ;
// Check for memory leaks..
2015-11-19 18:51:32 +01:00
CheckMemoryLeakInFunction checkMemoryLeak1 ( & tokenizer , & settings , this ) ;
CheckMemoryLeakInClass checkMemoryLeak2 ( & tokenizer , & settings , this ) ;
CheckMemoryLeakStructMember checkMemoryLeak3 ( & tokenizer , & settings , this ) ;
CheckMemoryLeakNoVar checkMemoryLeak4 ( & tokenizer , & settings , this ) ;
checkMemoryLeak1 . check ( ) ;
checkMemoryLeak1 . checkReallocUsage ( ) ;
checkMemoryLeak2 . check ( ) ;
checkMemoryLeak3 . check ( ) ;
checkMemoryLeak4 . check ( ) ;
2014-02-06 09:22:07 +01:00
}
2018-05-15 16:37:40 +02:00
void run ( ) override {
2014-03-24 09:59:05 +01:00
LOAD_LIB_2 ( settings . library , " gtk.cfg " ) ;
2015-11-19 18:51:32 +01:00
settings . addEnabled ( " all " ) ;
2014-03-24 09:59:05 +01:00
2014-02-06 09:22:07 +01:00
TEST_CASE ( glib1 ) ;
2015-11-19 18:51:32 +01:00
TEST_CASE ( glib2 ) ; // #2806 - FP when using redundant assignment
2014-02-06 09:22:07 +01:00
}
2014-11-20 14:20:09 +01:00
void glib1 ( ) {
2014-02-06 09:22:07 +01:00
check ( " void f(gchar *_a, gchar *_b) { "
" g_return_if_fail(_a); "
" gchar *a = g_strdup(_a); "
" g_return_if_fail(_b); "
" gchar *b = g_strdup(_b); "
" g_free(a); "
" g_free(b); "
" } " ) ;
2015-11-19 18:51:32 +01:00
ASSERT_EQUALS ( " [test.cpp:1]: (error) Memory leak: a \n " , errout . str ( ) ) ;
check ( " void x() { \n "
" g_strlcpy(a, g_strdup(p)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Allocation with g_strdup, g_strlcpy doesn't release it. \n " , errout . str ( ) ) ;
check ( " void f() \n "
" { \n "
" if(TRUE || g_strcmp0(g_strdup(a), b)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Allocation with g_strdup, g_strcmp0 doesn't release it. \n " , errout . str ( ) ) ;
check ( " void foo() \n "
" { \n "
" int *p = g_malloc(3); \n "
" g_free(p); \n "
" } \n " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (error) The allocated size 3 is not a multiple of the underlying type's size. \n " , " " , errout . str ( ) ) ;
check ( " class Fred \n "
" { \n "
" private: \n "
" char *str1; \n "
" public: \n "
" Fred() \n "
" { \n "
" str1 = new char[10]; \n "
" } \n "
" ~Fred() \n "
" { \n "
" g_free(str1); \n "
" } \n "
" }; " ) ;
ASSERT_EQUALS ( " [test.cpp:12]: (error) Mismatching allocation and deallocation: Fred::str1 \n " , errout . str ( ) ) ;
check ( " class Fred \n "
" { \n "
" private: \n "
" gchar *s; \n "
" public: \n "
" Fred() { s = 0; } \n "
" ~Fred() { g_free(s); } \n "
" void xy() \n "
" { s = g_malloc(100); } \n "
" }; " ) ;
ASSERT_EQUALS ( " [test.cpp:9]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated. \n " , errout . str ( ) ) ;
}
void glib2 ( ) {
// #2806 - FP when there is redundant assignment
check ( " void foo() { \n "
" gchar *bar; \n "
" bar = g_strdup(fuba); \n "
" bar = g_strstrip(bar); \n "
" g_free(bar); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void* foo() \n "
" { \n "
" char *p1 = g_malloc(10); \n "
" char *p2 = g_strlcpy(p1, \" a \" ); \n "
" return p2; \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " " , " [test.cpp:5]: (error) Memory leak: p1 \n " , errout . str ( ) ) ;
2014-02-06 09:22:07 +01:00
}
} ;
2015-10-07 14:30:01 +02:00
REGISTER_TEST ( TestMemleakGLib )
2014-06-01 00:00:49 +02:00
class TestMemleakWindows : public TestFixture {
public :
2014-11-20 14:20:09 +01:00
TestMemleakWindows ( ) : TestFixture ( " TestMemleakWindows " ) {
2014-06-01 00:00:49 +02:00
}
private :
Settings settings ;
2014-11-20 14:20:09 +01:00
void check ( const char code [ ] ) {
2014-06-01 00:00:49 +02:00
// Clear the error buffer..
errout . str ( " " ) ;
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
2015-10-07 14:05:55 +02:00
std : : istringstream istr ( code ) ;
2014-06-01 00:00:49 +02:00
tokenizer . tokenize ( istr , " test.c " ) ;
tokenizer . simplifyTokenList2 ( ) ;
// Check for memory leaks..
CheckMemoryLeakInFunction checkMemoryLeak ( & tokenizer , & settings , this ) ;
checkMemoryLeak . checkReallocUsage ( ) ;
checkMemoryLeak . check ( ) ;
}
2018-05-15 16:37:40 +02:00
void run ( ) override {
2014-06-01 00:00:49 +02:00
LOAD_LIB_2 ( settings . library , " windows.cfg " ) ;
TEST_CASE ( openfileNoLeak ) ;
2016-06-02 09:41:01 +02:00
TEST_CASE ( returnValueNotUsed_tfopen_s ) ;
2016-07-26 11:57:26 +02:00
TEST_CASE ( sendMessage ) ;
2014-06-01 00:00:49 +02:00
}
2014-11-20 14:20:09 +01:00
void openfileNoLeak ( ) {
2014-06-01 00:00:49 +02:00
check ( " void f() { "
" OFSTRUCT OfStr; "
" int hFile = OpenFile( \" file \" , &OfStr, 0); "
" } " ) ;
ASSERT_EQUALS ( " [test.c:1]: (error) Resource leak: hFile \n " , errout . str ( ) ) ;
check ( " void f() { "
" OFSTRUCT OfStr; "
" int hFile = OpenFile( \" file \" , &OfStr, OF_EXIST); "
" } " ) ;
TODO_ASSERT_EQUALS ( " " , " [test.c:1]: (error) Resource leak: hFile \n " , errout . str ( ) ) ;
}
2016-06-02 09:41:01 +02:00
void returnValueNotUsed_tfopen_s ( ) {
check ( " bool LoadFile(LPCTSTR filename) { \n "
" FILE *fp = NULL; \n "
" _tfopen_s(&fp, filename, _T( \" rb \" )); \n "
" if (!fp) \n "
" return false; \n "
" fclose(fp); \n "
" return true; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " bool LoadFile(LPCTSTR filename) { \n "
" FILE *fp = NULL; \n "
" _tfopen_s(&fp, filename, _T( \" rb \" )); \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " [test.c:3]: (error) Resource leak: fp \n " , " " , errout . str ( ) ) ;
}
2016-07-26 11:57:26 +02:00
void sendMessage ( ) {
check ( " void SetFont() { \n "
" HFONT hf = CreateFontIndirect(&lf); \n "
" SendMessage(hwnd, WM_SETFONT, (WPARAM)hf, TRUE); \n " // We do not know what the handler for the message will do with 'hf', so it might be closed later
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-06-01 00:00:49 +02:00
} ;
2015-10-07 14:30:01 +02:00
REGISTER_TEST ( TestMemleakWindows )