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
2022-02-05 11:45:17 +01:00
* Copyright ( C ) 2007 - 2022 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
*/
2022-01-27 19:03:20 +01:00
2009-10-25 12:49:06 +01:00
# include "checkmemoryleak.h"
2022-01-27 19:03:20 +01:00
# include "errortypes.h"
2017-05-27 04:33:47 +02:00
# include "settings.h"
# include "symboldatabase.h"
# include "testsuite.h"
# include "token.h"
# include "tokenize.h"
2022-01-27 19:03:20 +01:00
# include <iosfwd>
2017-05-27 04:33:47 +02:00
# include <list>
2022-01-27 19:03:20 +01:00
# include <memory>
2017-05-27 04:33:47 +02:00
# include <string>
2008-12-18 22:28:57 +01:00
2022-01-27 19:03:20 +01:00
class TestMemleakInClass ;
class TestMemleakNoVar ;
class TestMemleakStructMember ;
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 :
2021-08-07 20:51:18 +02:00
TestMemleak ( ) : TestFixture ( " TestMemleak " ) { }
2009-06-15 17:44:59 +02:00
private :
2015-10-07 18:33:57 +02:00
Settings settings ;
2022-02-10 23:02:24 +01: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
}
2021-11-29 07:34:39 +01:00
# define functionReturnType(code) functionReturnType_(code, __FILE__, __LINE__)
CheckMemoryLeak : : AllocType functionReturnType_ ( const char code [ ] , const char * file , int line ) {
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 ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , " test.cpp " ) , file , line ) ;
2009-06-15 17:44:59 +02:00
2018-09-24 15:08:16 +02:00
const CheckMemoryLeak c ( & tokenizer , this , & settings ) ;
2013-06-29 12:55:24 +02:00
2021-11-29 07:34:39 +01: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 ) ;
2021-11-29 07:34:39 +01:00
ASSERT ( tokenizer . tokenize ( istr , " test.cpp " ) ) ;
2010-01-26 20:10:52 +01:00
// there is no allocation
2011-10-28 22:30:33 +02:00
const Token * tok = Token : : findsimplematch ( tokenizer . tokens ( ) , " ret = " ) ;
2019-06-30 21:39:22 +02:00
const CheckMemoryLeak check ( & tokenizer , nullptr , & 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
2019-07-05 12:44:52 +02:00
class TestMemleakInFunction : public TestFixture {
public :
2021-08-07 20:51:18 +02:00
TestMemleakInFunction ( ) : TestFixture ( " TestMemleakInFunction " ) { }
2019-07-05 12:44:52 +02:00
private :
Settings settings0 ;
Settings settings1 ;
Settings settings2 ;
2021-11-29 07:34:39 +01:00
# define check(...) check_(__FILE__, __LINE__, __VA_ARGS__)
void check_ ( const char * file , int line , const char code [ ] ) {
2019-07-05 12:44:52 +02:00
// Clear the error buffer..
errout . str ( " " ) ;
Settings * settings = & settings1 ;
// Tokenize..
Tokenizer tokenizer ( settings , this ) ;
std : : istringstream istr ( code ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , " test.cpp " ) , file , line ) ;
2019-07-05 12:44:52 +02:00
// Check for memory leaks..
CheckMemoryLeakInFunction checkMemoryLeak ( & tokenizer , settings , this ) ;
checkMemoryLeak . checkReallocUsage ( ) ;
}
2022-02-10 23:02:24 +01:00
void run ( ) override {
2019-07-05 12:44:52 +02:00
LOAD_LIB_2 ( settings1 . library , " std.cfg " ) ;
LOAD_LIB_2 ( settings1 . library , " posix.cfg " ) ;
LOAD_LIB_2 ( settings2 . library , " std.cfg " ) ;
TEST_CASE ( realloc1 ) ;
TEST_CASE ( realloc2 ) ;
TEST_CASE ( realloc3 ) ;
TEST_CASE ( realloc4 ) ;
TEST_CASE ( realloc5 ) ;
TEST_CASE ( realloc7 ) ;
TEST_CASE ( realloc8 ) ;
TEST_CASE ( realloc9 ) ;
TEST_CASE ( realloc10 ) ;
TEST_CASE ( realloc11 ) ;
TEST_CASE ( realloc12 ) ;
TEST_CASE ( realloc13 ) ;
TEST_CASE ( realloc14 ) ;
TEST_CASE ( realloc15 ) ;
TEST_CASE ( realloc16 ) ;
2019-07-22 10:37:36 +02:00
TEST_CASE ( realloc17 ) ;
TEST_CASE ( realloc18 ) ;
TEST_CASE ( realloc19 ) ;
TEST_CASE ( realloc20 ) ;
2019-12-04 12:13:44 +01:00
TEST_CASE ( realloc21 ) ;
TEST_CASE ( realloc22 ) ;
TEST_CASE ( realloc23 ) ;
2020-07-31 01:44:33 +02:00
TEST_CASE ( realloc24 ) ; // #9228
2019-07-22 10:37:36 +02:00
TEST_CASE ( reallocarray1 ) ;
2019-07-05 12:44:52 +02:00
}
void realloc1 ( ) {
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" a = realloc(a, 100); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' a \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
}
void realloc2 ( ) {
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" a = (char *)realloc(a, 100); \n "
" free(a); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' a \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
}
void realloc3 ( ) {
check ( " void foo() \n "
" { \n "
" char *a = 0; \n "
" if ((a = realloc(a, 100)) == NULL) \n "
" return; \n "
" free(a); \n "
" } " ) ;
2020-09-12 18:46:01 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-07-05 12:44:52 +02:00
}
void realloc4 ( ) {
check ( " void foo() \n "
" { \n "
" static char *a = 0; \n "
" if ((a = realloc(a, 100)) == NULL) \n "
" return; \n "
" free(a); \n "
" } " ) ;
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 ( ) ) ;
}
void realloc5 ( ) {
check ( " void foo() \n "
" { \n "
" 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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:44:52 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc7 ( ) {
check ( " bool foo(size_t nLen, char* pData) \n "
" { \n "
" pData = (char*) realloc(pData, sizeof(char) + (nLen + 1)*sizeof(char)); \n "
" if ( pData == NULL ) \n "
" { \n "
" return false; \n "
" } \n "
" free(pData); \n "
" return true; \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:44:52 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc8 ( ) {
check ( " void foo() \n "
" { \n "
" char *origBuf = m_buf; \n "
" m_buf = (char *) realloc (m_buf, m_capacity + growBy); \n "
" if (!m_buf) { \n "
" m_buf = origBuf; \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:44:52 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc9 ( ) {
check ( " void foo() \n "
" { \n "
" x = realloc(x,100); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:44:52 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc10 ( ) {
check ( " void foo() { \n "
" char *pa, *pb; \n "
" pa = pb = malloc(10); \n "
" pa = realloc(pa, 20); "
" exit(); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:44:52 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc11 ( ) {
check ( " void foo() { \n "
" char *p; \n "
" p = realloc(p, size); \n "
" if (!p) \n "
" error(); \n "
" usep(p); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:44:52 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc12 ( ) {
check ( " void foo(int x) \n "
" { \n "
" char *a = 0; \n "
" if ((a = realloc(a, x + 100)) == NULL) \n "
" return; \n "
" free(a); \n "
" } " ) ;
2020-09-12 18:46:01 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-07-05 12:44:52 +02:00
}
void realloc13 ( ) {
check ( " void foo() \n "
" { \n "
" char **str; \n "
" *str = realloc(*str,100); \n "
" free (*str); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' str \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
}
void realloc14 ( ) {
check ( " void foo() { \n "
" char *p; \n "
" p = realloc(p, size + 1); \n "
" if (!p) \n "
" error(); \n "
" usep(p); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:44:52 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc15 ( ) {
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:44:52 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Common realloc mistake: \' m_options \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
}
void realloc16 ( ) {
check ( " void f(char *zLine) { \n "
" zLine = realloc(zLine, 42); \n "
" if (zLine) { \n "
" free(zLine); \n "
" } \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-05 12:44:52 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-07-22 10:37:36 +02:00
void realloc17 ( ) {
check ( " void foo() \n "
" { \n "
" void ***a = malloc(sizeof(a)); \n "
" ***a = realloc(***(a), sizeof(a) * 2); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' a \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
}
void realloc18 ( ) {
check ( " void foo() \n "
" { \n "
" void *a = malloc(sizeof(a)); \n "
" a = realloc((void*)a, sizeof(a) * 2); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' a \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
}
void realloc19 ( ) {
check ( " void foo() \n "
" { \n "
" void *a = malloc(sizeof(a)); \n "
" a = (realloc((void*)((a)), sizeof(a) * 2)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' a \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
}
void realloc20 ( ) {
check ( " void foo() \n "
" { \n "
" void *a = malloc(sizeof(a)); \n "
" a = realloc((a) + 1, sizeof(a) * 2); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-12-04 12:13:44 +01:00
void realloc21 ( ) {
check ( " char *foo(char *bs0) \n "
" { \n "
" char *bs = bs0; \n "
" bs = realloc(bs, 100); \n "
" if (bs == NULL) return bs0; \n "
" return bs; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc22 ( ) {
check ( " void foo(char **bsp) \n "
" { \n "
" char *bs = *bsp; \n "
" bs = realloc(bs, 100); \n "
" if (bs == NULL) return; \n "
" *bsp = bs; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc23 ( ) {
check ( " void foo(struct ABC *s) \n "
" { \n "
" uint32_t *cigar = s->cigar; \n "
" if (!(cigar = realloc(cigar, 100 * sizeof(*cigar)))) \n "
" return; \n "
" s->cigar = cigar; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-07-31 01:44:33 +02:00
void realloc24 ( ) { // #9228
check ( " void f() { \n "
" void *a = NULL; \n "
" a = realloc(a, 20); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" void *a = NULL; \n "
" a = malloc(10); \n "
" a = realloc(a, 20); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' a \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" void *a = std::nullptr; \n "
" a = malloc(10); \n "
" a = realloc(a, 20); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common realloc mistake: \' a \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
check ( " void f(char *b) { \n "
" void *a = NULL; \n "
" a = b; \n "
" a = realloc(a, 20); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-07-22 10:37:36 +02:00
void reallocarray1 ( ) {
check ( " void foo() \n "
" { \n "
" char *a = (char *)malloc(10); \n "
" a = reallocarray(a, 100, 2); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Common reallocarray mistake: \' a \' nulled but not freed upon failure \n " , errout . str ( ) ) ;
}
2019-07-05 12:44:52 +02:00
} ;
REGISTER_TEST ( TestMemleakInFunction )
2011-10-13 20:53:06 +02:00
class TestMemleakInClass : public TestFixture {
2009-06-08 20:20:43 +02:00
public :
2021-08-07 20:51:18 +02:00
TestMemleakInClass ( ) : TestFixture ( " TestMemleakInClass " ) { }
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
*/
2021-11-29 07:34:39 +01:00
void check_ ( const char * file , int line , 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 ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , " test.cpp " ) , file , line ) ;
2009-06-08 20:20:43 +02:00
// Check for memory leaks..
CheckMemoryLeakInClass checkMemoryLeak ( & tokenizer , & settings , this ) ;
2021-11-29 07:34:39 +01:00
( checkMemoryLeak . check ) ( ) ;
2009-06-08 20:20:43 +02:00
}
2022-02-10 23:02:24 +01:00
void run ( ) override {
2021-02-24 22:00:06 +01:00
settings . severity . enable ( Severity : : warning ) ;
settings . severity . enable ( Severity : : style ) ;
2015-10-07 18:33:57 +02:00
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
2022-02-04 19:32:23 +01:00
TEST_CASE ( class26 ) ; // ticket #10789
2022-02-15 14:28:19 +01:00
TEST_CASE ( class27 ) ; // ticket #8126
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
" } " ) ;
2021-11-29 07:06:43 +01:00
TODO_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 " ,
" [test.cpp:9]: (style) Class 'A' is unsafe, 'A::b' 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
" } " ) ;
2021-11-29 07:06:43 +01:00
TODO_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 " ,
" [test.cpp:9]: (style) Class 'A' is unsafe, 'A::b' 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 ( ) ) ;
}
2022-02-04 19:32:23 +01:00
void class26 ( ) { // ticket #10789 - crash
check ( " class C; \n "
" struct S { \n "
" S() { p = new C; } \n "
" ~S(); \n "
" C* p; \n "
" }; \n "
" S::~S() = default; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (style) Class 'S' is unsafe, 'S::p' can leak by wrong usage. \n " , errout . str ( ) ) ;
}
2022-02-15 14:28:19 +01:00
void class27 ( ) { // ticket #8126 - array of pointers
check ( " struct S { \n "
" S() { \n "
2022-02-15 20:03:02 +01:00
" for (int i = 0; i < 5; i++) \n "
" a[i] = new char[3]; \n "
2022-02-15 14:28:19 +01:00
" } \n "
2022-02-15 20:03:02 +01:00
" char* a[5]; \n "
2022-02-15 14:28:19 +01:00
" }; \n " ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (style) Class 'S' is unsafe, 'S::a' can leak by wrong usage. \n " , 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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
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 :
2021-08-07 20:51:18 +02:00
TestMemleakStructMember ( ) : TestFixture ( " TestMemleakStructMember " ) { }
2009-06-16 22:01:04 +02:00
private :
2015-10-07 18:33:57 +02:00
Settings settings ;
2021-11-29 07:34:39 +01:00
void check_ ( const char * file , int line , 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 ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , isCPP ? " test.cpp " : " test.c " ) , file , line ) ;
2009-06-16 22:01:04 +02:00
// Check for memory leaks..
CheckMemoryLeakStructMember checkMemoryLeakStructMember ( & tokenizer , & settings , this ) ;
2021-11-29 07:34:39 +01:00
( checkMemoryLeakStructMember . check ) ( ) ;
2009-06-16 22:01:04 +02:00
}
2022-02-10 23:02:24 +01: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 ) ;
2022-05-23 23:21:36 +02:00
TEST_CASE ( assign4 ) ; // #11019
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
2022-02-02 13:13:12 +01:00
TEST_CASE ( function5 ) ; // #10381, #10382, #10158
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
2019-01-09 20:38:32 +01:00
// struct variable is a reference variable
TEST_CASE ( refvar ) ;
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 ) ;
2020-07-07 21:36:14 +02:00
TEST_CASE ( lambdaInForLoop ) ; // #9793
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
}
2022-05-23 23:21:36 +02:00
void assign4 ( ) {
check ( " struct S { int a, b, c; }; \n " // #11019
" void f() { \n "
" struct S s; \n "
" *&s.a = open( \" xx.log \" , O_RDONLY); \n "
" ((s).b) = open( \" xx.log \" , O_RDONLY); \n "
" (&s)->c = open( \" xx.log \" , O_RDONLY); \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " [test.c:7]: (error) Memory leak: s.a \n "
" [test.c:7]: (error) Memory leak: s.b \n "
" [test.c:7]: (error) Memory leak: s.c \n " ,
errout . str ( ) ) ;
check ( " struct S { int *p, *q; }; \n " // #7705
" void f(S s) { \n "
" s.p = new int[10]; \n "
" s.q = malloc(40); \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: s.p \n "
" [test.cpp:5]: (error) Memory leak: s.q \n " ,
errout . str ( ) ) ;
2022-05-24 14:02:06 +02:00
check ( " struct S** f(struct S** s) { \n " // don't throw
" struct S** ret = malloc(sizeof(*ret)); \n "
" ret[0] = malloc(sizeof(**s)); \n "
" ret[0]->g = strdup(s[0]->g); \n "
" return ret; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void run_rcmd(enum rcommand rcmd, rsh_session *sess, char *cmd) { \n "
" sess->fp = popen(cmd, rcmd == RSH_PIPE_READ ? \" r \" : \" w \" ); \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-26 00:03:30 +02:00
check ( " struct S { char* a[2]; }; \n "
" enum E { E0, E1 }; \n "
" void f(struct S* s, enum E e, const char* n) { \n "
" free(s->a[e]); \n "
" s->a[e] = strdup(n); \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-26 15:27:36 +02:00
check ( " void f(struct S** s, const char* c) { \n "
" *s = malloc(sizeof(struct S)); \n "
" (*s)->value = strdup(c); \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct S { \n "
" size_t mpsz; \n "
" void* hdr; \n "
" }; \n "
" void f(struct S s[static 1U], int fd, size_t size) { \n "
" s->mpsz = size; \n "
" s->hdr = mmap(NULL, s->mpsz, PROT_READ, MAP_SHARED, fd, 0); \n "
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-27 23:52:56 +02:00
check ( " void f(type_t t) { \n "
" t->p = malloc(10); \n "
2022-05-30 06:55:15 +02:00
" t->x.p = malloc(10); \n "
" t->y[2].p = malloc(10); \n "
2022-05-27 23:52:56 +02:00
" } \n " , false ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-05-23 23:21:36 +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
}
2021-11-29 22:51:35 +01:00
void function5 ( ) {
check ( " struct s f() { \n " // #10381
" struct s s1; \n "
" s1->x = malloc(1); \n "
" return (s1); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-12-01 09:51:48 +01:00
check ( " struct nc_rpc nc_rpc_getconfig() { \n " // #10382
2021-11-29 22:51:35 +01:00
" struct nc_rpc rpc; \n "
" rpc->filter = malloc(1); \n "
" return (nc_rpc)rpc; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-02-02 13:13:12 +01:00
check ( " T* f(const char *str) { \n " // #10158
" S* s = malloc(sizeof(S)); \n "
" s->str = strdup(str); \n "
" return NewT(s); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-29 22:51:35 +01: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
2019-01-09 20:38:32 +01:00
void refvar ( ) { // #8116
check ( " struct Test \n "
" { \n "
" int* data; \n "
" }; \n "
" \n "
" void foo(Test* x) \n "
" { \n "
" Test& y = *x; \n "
" y.data = malloc(10); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
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 ) ;
2022-05-23 23:21:36 +02:00
ASSERT_EQUALS ( " [test.c:6]: (error) Memory leak: f.realm \n " , errout . str ( ) ) ;
2014-05-08 20:51:18 +02:00
}
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 ( ) ) ;
}
2020-07-07 21:36:14 +02:00
void lambdaInForLoop ( ) { // #9793
check (
" struct S { int * p{nullptr}; }; \n "
" int main() \n "
" { \n "
" S s; \n "
" s.p = new int[10]; \n "
" for (int i = 0; i < 10; ++i) { \n "
" s.p[i] = []() { return 1; }(); \n "
" } \n "
" delete[] s.p; \n "
" return 0; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , 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 :
2021-08-07 20:51:18 +02:00
TestMemleakNoVar ( ) : TestFixture ( " TestMemleakNoVar " ) { }
2010-11-12 21:09:34 +01:00
private :
2014-03-24 09:59:05 +01:00
Settings settings ;
2021-11-29 07:34:39 +01:00
void check_ ( const char * file , int line , 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 ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , " test.cpp " ) , file , line ) ;
2014-03-24 09:59:05 +01:00
// Check for memory leaks..
CheckMemoryLeakNoVar checkMemoryLeakNoVar ( & tokenizer , & settings , this ) ;
2021-11-29 07:34:39 +01:00
( checkMemoryLeakNoVar . check ) ( ) ;
2014-03-24 09:59:05 +01:00
}
2022-02-10 23:02:24 +01:00
void run ( ) override {
2021-02-24 22:00:06 +01:00
settings . certainty . setEnabled ( Certainty : : inconclusive , true ) ;
2019-09-25 15:25:19 +02:00
settings . libraries . emplace_back ( " posix " ) ;
2021-02-24 22:00:06 +01:00
settings . severity . enable ( Severity : : 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 ) ;
2019-02-03 12:15:05 +01:00
// Test getAllocationType for subfunction
TEST_CASE ( getAllocationType ) ;
2022-01-18 20:50:06 +01:00
TEST_CASE ( crash1 ) ; // #10729
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 ( ) ) ;
2021-05-08 15:28:21 +02:00
2021-05-08 10:26:10 +02:00
check ( " char *x() { \n "
" return strcpy(malloc(10), \" abc \" ); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2011-11-11 09:07:02 +01:00
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 ( ) ) ;
2019-08-12 12:53:59 +02:00
check ( " void f() { \n "
" assert(freopen( \" /dev/null \" , \" r \" , stdin)); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-08-14 22:01:40 +02:00
check ( " void x() { \n "
" strcpy(a, (void*)strdup(p)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Allocation with strdup, strcpy doesn't release it. \n " , errout . str ( ) ) ;
check ( " void* malloc1() { \n "
" return (malloc(1)); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " char *x() { \n "
" char *ret = (char*)strcpy(malloc(10), \" abc \" ); \n "
" return ret; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-08-23 06:33:00 +02:00
check ( " void f() { \n "
" free(malloc(1)); \n "
" strcpy(a, strdup(p)); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Allocation with strdup, strcpy doesn't release it. \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" memcmp(calloc(10, 10), strdup(q), 100); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Allocation with calloc, memcmp doesn't release it. \n "
" [test.cpp:2]: (error) Allocation with strdup, memcmp doesn't release it. \n " , errout . str ( ) ) ;
2019-10-30 17:55:47 +01:00
check ( " void* f(int size) { \n "
" return (void*) malloc(size); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int* f(int size) { \n "
" return static_cast<int*>(malloc(size)); \n "
" } " ) ;
ASSERT_EQUALS ( " " , 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
2019-07-22 10:37:36 +02:00
check ( " void x() \n "
" { \n "
" reallocarray(NULL, 10, 10); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Return value of allocation function 'reallocarray' 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 "
" } " ) ;
2020-02-21 21:11:32 +01:00
TODO_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
2018-11-12 11:28:26 +01:00
check ( " void f() \n " // #8100
" { \n "
" auto lambda = [](){return malloc(10);}; \n "
" } \n "
" void x() \n "
" { \n "
" f(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-04-22 17:37:41 +02:00
check ( " void *f() { \n " // #8848
" struct S { void *alloc() { return malloc(10); } }; \n "
" } \n "
" void x() \n "
" { \n "
" f(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , 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 ( ) ) ;
2022-04-09 19:06:32 +02:00
check ( " void f() { \n "
" new int[10]; \n "
" new int[10][5]; \n "
" new int[10](); \n "
" new int[10]{}; \n "
" new int[] { 1, 2, 3 }; \n "
" new std::string; \n "
" new int; \n "
" new int(); \n "
" new int(1); \n "
" new int{}; \n "
" new int{ 1 }; \n "
" new uint8_t[4]; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:3]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:4]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:5]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:6]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:7]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:8]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:9]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:10]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:11]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:12]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:13]: (error) Return value of allocation function 'new' is not stored. \n " ,
errout . str ( ) ) ;
check ( " void f(int* p) { \n "
" new auto('c'); \n "
" new(p) int; \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (error) Return value of allocation function 'new' is not stored. \n "
" [test.cpp:3]: (error) Return value of allocation function 'new' is not stored. \n " ,
" " ,
errout . str ( ) ) ;
check ( " void g(int* p) { \n "
" new QWidget; \n "
" new QWidget(); \n "
" new QWidget{ this }; \n "
" h(new int[10], 1); \n "
" h(new int[10][5], 1); \n "
" h(new int[10](), 1); \n "
" h(new int[10]{}, 1); \n "
" h(new int[] { 1, 2, 3 }, 1); \n "
" h(new auto('c'), 1); \n "
" h(new std::string, 1); \n "
" h(new int, 1); \n "
" h(new int{}, 1); \n "
" h(new int(), 1); \n "
" h(new int{ 1 }, 1); \n "
" h(new int(1), 1); \n "
" h(new(p) int, 1); \n "
" h(new QWidget, 1); \n "
" C{ new int[10], 1 }; \n "
" C{ new int[10](), 1 }; \n "
" C{ new int[10]{}, 1 }; \n "
" C{ new int[] { 1, 2, 3 }, 1 }; \n "
" C{ new auto('c'), 1 }; \n "
" C{ new std::string, 1 }; \n "
" C{ new int, 1 }; \n "
" C{ new int{}, 1 }; \n "
" C{ new int(), 1 }; \n "
" C{ new int{ 1 }, 1 }; \n "
" C{ new int(1), 1 }; \n "
" C{ new(p) int, 1 }; \n "
" C{ new QWidget, 1 }; \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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-04-05 06:47:59 +02:00
ASSERT_EQUALS ( " [test.cpp:2]: (error) Return value of allocation function 'fopen' is not stored. \n " , errout . str ( ) ) ;
2019-07-22 10:37:36 +02:00
check ( " void foo() { \n "
" FILE f* = fopen( \" file.txt \" , \" r \" ); \n "
" freopen( \" file.txt \" , \" r \" , f); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-22 10:37:36 +02:00
ASSERT_EQUALS ( " [test.cpp:3]: (error) Return value of allocation function 'freopen' is not stored. \n " , errout . str ( ) ) ;
2019-07-25 21:09:23 +02:00
check ( " void foo() { \n "
" freopen( \" file.txt \" , \" r \" , stdin); \n "
2021-02-20 12:58:42 +01:00
" } " ) ;
2019-07-25 21:09:23 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-04-05 06:47:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-04-05 06:47:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-04-05 06:47:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-04-05 06:47:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-04-05 06:47:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-04-05 06:47:59 +02:00
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 "
2021-02-20 12:58:42 +01:00
" } " ) ;
2018-04-05 06:47:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-02-03 12:15:05 +01:00
void getAllocationType ( ) {
// #7845
check ( " class Thing { Thing(); }; \n "
" Thing * makeThing() { Thing *thing = new Thing; return thing; } \n "
" \n "
" void f() { \n "
" makeThing(); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2021-11-29 07:06:43 +01:00
// #10631
check ( " struct Thing { \n "
" Thing(); \n "
" }; \n "
" std::vector<Thing*> g_things; \n "
" Thing* makeThing() { \n "
" Thing* n = new Thing(); \n "
" return n; \n "
" } \n "
" Thing::Thing() { \n "
" g_things.push_back(this); \n "
" } \n "
" void f() { \n "
" makeThing(); \n "
" for(Thing* t : g_things) { \n "
" delete t; \n "
" } \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-02-03 12:15:05 +01:00
}
2022-01-18 20:50:06 +01:00
void crash1 ( ) { // #10729
check ( " void foo() { \n "
" extern void *realloc (void *ptr, size_t size); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void foo() { \n "
" extern void *malloc (size_t size); \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