2012-05-26 08:53:46 +02:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2023-01-28 10:16:34 +01:00
* Copyright ( C ) 2007 - 2023 Cppcheck team .
2012-05-26 08:53:46 +02: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
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2017-05-27 04:33:47 +02:00
2012-05-26 08:53:46 +02:00
# include "checkleakautovar.h"
2022-01-27 19:03:20 +01:00
# include "errortypes.h"
2017-05-27 04:33:47 +02:00
# include "library.h"
# include "settings.h"
2023-01-27 08:18:32 +01:00
# include "fixture.h"
2017-05-27 04:33:47 +02:00
# include "tokenize.h"
2012-05-26 08:53:46 +02:00
2022-01-27 19:03:20 +01:00
# include <map>
2022-09-16 07:15:49 +02:00
# include <sstream> // IWYU pragma: keep
2022-01-27 19:03:20 +01:00
# include <string>
# include <utility>
# include <vector>
2019-07-12 07:56:05 +02:00
# include <simplecpp.h>
2022-01-27 19:03:20 +01:00
2019-09-21 14:59:54 +02:00
# include <tinyxml2.h>
2022-01-27 19:03:20 +01:00
class TestLeakAutoVarStrcpy ;
class TestLeakAutoVarWindows ;
2012-05-26 08:53:46 +02:00
class TestLeakAutoVar : public TestFixture {
public :
2021-08-07 20:51:18 +02:00
TestLeakAutoVar ( ) : TestFixture ( " TestLeakAutoVar " ) { }
2012-05-26 08:53:46 +02:00
private :
2015-10-07 18:33:57 +02:00
Settings settings ;
2012-05-26 08:53:46 +02:00
2022-02-10 23:02:24 +01:00
void run ( ) override {
2015-10-07 18:33:57 +02:00
int id = 0 ;
2019-09-20 21:54:30 +02:00
while ( ! Library : : ismemory ( + + id ) ) ;
2016-05-22 17:18:50 +02:00
settings . library . setalloc ( " malloc " , id , - 1 ) ;
2019-07-05 12:44:52 +02:00
settings . library . setrealloc ( " realloc " , id , - 1 ) ;
2016-05-22 17:18:50 +02:00
settings . library . setdealloc ( " free " , id , 1 ) ;
2021-03-03 06:58:38 +01:00
while ( ! Library : : isresource ( + + id ) ) ;
2020-10-29 13:17:33 +01:00
settings . library . setalloc ( " socket " , id , - 1 ) ;
settings . library . setdealloc ( " close " , id , 1 ) ;
2019-09-20 21:54:30 +02:00
while ( ! Library : : isresource ( + + id ) ) ;
2016-05-22 17:18:50 +02:00
settings . library . setalloc ( " fopen " , id , - 1 ) ;
2019-07-05 12:44:52 +02:00
settings . library . setrealloc ( " freopen " , id , - 1 , 3 ) ;
2016-05-22 17:18:50 +02:00
settings . library . setdealloc ( " fclose " , id , 1 ) ;
2021-07-20 21:30:27 +02:00
settings . library . smartPointers [ " std::shared_ptr " ] ;
settings . library . smartPointers [ " std::unique_ptr " ] ;
settings . library . smartPointers [ " std::unique_ptr " ] . unique = true ;
2015-10-07 18:33:57 +02:00
2019-09-21 14:59:54 +02:00
const char xmldata [ ] = " <?xml version= \" 1.0 \" ?> \n "
2021-08-07 20:51:18 +02:00
" <def> \n "
" <podtype name= \" uint8_t \" sign= \" u \" size= \" 1 \" /> \n "
" </def> " ;
2019-09-21 14:59:54 +02:00
tinyxml2 : : XMLDocument doc ;
doc . Parse ( xmldata , sizeof ( xmldata ) ) ;
settings . library . load ( doc ) ;
2012-05-26 08:53:46 +02:00
// Assign
TEST_CASE ( assign1 ) ;
TEST_CASE ( assign2 ) ;
TEST_CASE ( assign3 ) ;
TEST_CASE ( assign4 ) ;
TEST_CASE ( assign5 ) ;
TEST_CASE ( assign6 ) ;
TEST_CASE ( assign7 ) ;
TEST_CASE ( assign8 ) ;
TEST_CASE ( assign9 ) ;
2012-05-26 21:28:35 +02:00
TEST_CASE ( assign10 ) ;
2012-08-21 17:02:11 +02:00
TEST_CASE ( assign11 ) ; // #3942: x = a(b(p));
2012-10-25 19:41:18 +02:00
TEST_CASE ( assign12 ) ; // #4236: FP. bar(&x);
2021-02-20 13:02:14 +01:00
TEST_CASE ( assign13 ) ; // #4237: FP. char*&ref=p; p=malloc(10); free(ref);
2017-10-26 19:11:00 +02:00
TEST_CASE ( assign14 ) ;
2019-06-02 15:25:45 +02:00
TEST_CASE ( assign15 ) ;
TEST_CASE ( assign16 ) ;
2019-07-03 08:39:44 +02:00
TEST_CASE ( assign17 ) ; // #9047
TEST_CASE ( assign18 ) ;
2019-07-10 09:13:59 +02:00
TEST_CASE ( assign19 ) ;
2020-02-22 21:26:26 +01:00
TEST_CASE ( assign20 ) ; // #9187
2021-02-25 10:55:34 +01:00
TEST_CASE ( assign21 ) ; // #10186
2021-03-03 06:58:38 +01:00
TEST_CASE ( assign22 ) ; // #9139
2022-05-01 15:46:07 +02:00
TEST_CASE ( assign23 ) ;
2022-06-25 08:38:17 +02:00
TEST_CASE ( assign24 ) ; // #7440
2012-05-26 08:53:46 +02:00
2019-07-17 08:59:09 +02:00
TEST_CASE ( isAutoDealloc ) ;
2019-07-05 12:44:52 +02:00
TEST_CASE ( realloc1 ) ;
TEST_CASE ( realloc2 ) ;
TEST_CASE ( realloc3 ) ;
2021-01-11 07:55:05 +01:00
TEST_CASE ( realloc4 ) ;
TEST_CASE ( realloc5 ) ; // #9292, #9990
2019-07-05 12:44:52 +02:00
TEST_CASE ( freopen1 ) ;
TEST_CASE ( freopen2 ) ;
2012-05-26 08:53:46 +02:00
TEST_CASE ( deallocuse1 ) ;
TEST_CASE ( deallocuse2 ) ;
TEST_CASE ( deallocuse3 ) ;
2012-06-11 18:28:31 +02:00
TEST_CASE ( deallocuse4 ) ;
2021-02-20 13:02:14 +01:00
TEST_CASE ( deallocuse5 ) ; // #4018: FP. free(p), p = 0;
2012-08-28 06:38:38 +02:00
TEST_CASE ( deallocuse6 ) ; // #4034: FP. x = p = f();
2015-01-29 21:26:06 +01:00
TEST_CASE ( deallocuse7 ) ; // #6467, #6469, #6473
2019-07-12 18:25:04 +02:00
TEST_CASE ( deallocuse8 ) ; // #1765
2022-01-19 21:39:45 +01:00
TEST_CASE ( deallocuse9 ) ; // #9781
2012-05-26 08:53:46 +02:00
2012-07-16 17:07:51 +02:00
TEST_CASE ( doublefree1 ) ;
TEST_CASE ( doublefree2 ) ;
2013-07-28 10:26:46 +02:00
TEST_CASE ( doublefree3 ) ; // #4914
2014-05-04 12:02:55 +02:00
TEST_CASE ( doublefree4 ) ; // #5451 - FP when exit is called
2016-05-26 19:21:45 +02:00
TEST_CASE ( doublefree5 ) ; // #5522
2016-12-29 13:17:46 +01:00
TEST_CASE ( doublefree6 ) ; // #7685
2017-10-26 19:11:00 +02:00
TEST_CASE ( doublefree7 ) ;
2018-04-16 11:11:13 +02:00
TEST_CASE ( doublefree8 ) ;
2018-04-21 11:24:19 +02:00
TEST_CASE ( doublefree9 ) ;
2019-08-07 08:04:10 +02:00
TEST_CASE ( doublefree10 ) ; // #8706
2021-01-11 07:55:05 +01:00
TEST_CASE ( doublefree11 ) ;
2022-03-21 22:17:50 +01:00
TEST_CASE ( doublefree12 ) ; // #10502
2022-07-19 20:41:08 +02:00
TEST_CASE ( doublefree13 ) ; // #11008
2018-04-21 11:24:19 +02:00
2012-05-26 08:53:46 +02:00
// exit
TEST_CASE ( exit1 ) ;
TEST_CASE ( exit2 ) ;
2017-02-25 11:36:48 +01:00
TEST_CASE ( exit3 ) ;
2012-05-26 08:53:46 +02:00
2017-07-07 21:51:48 +02:00
// handling function calls
TEST_CASE ( functioncall1 ) ;
2012-05-26 08:53:46 +02:00
// goto
TEST_CASE ( goto1 ) ;
2012-10-08 17:23:47 +02:00
TEST_CASE ( goto2 ) ;
2022-12-14 22:47:14 +01:00
TEST_CASE ( goto3 ) ; // #11431
2012-05-26 08:53:46 +02:00
// if/else
TEST_CASE ( ifelse1 ) ;
TEST_CASE ( ifelse2 ) ;
TEST_CASE ( ifelse3 ) ;
TEST_CASE ( ifelse4 ) ;
2012-05-29 21:10:19 +02:00
TEST_CASE ( ifelse5 ) ;
2012-06-04 21:21:14 +02:00
TEST_CASE ( ifelse6 ) ; // #3370
2014-04-18 18:18:47 +02:00
TEST_CASE ( ifelse7 ) ; // #5576 - if (fd < 0)
2014-09-17 18:37:41 +02:00
TEST_CASE ( ifelse8 ) ; // #5747 - if (fd == -1)
2017-06-30 23:05:09 +02:00
TEST_CASE ( ifelse9 ) ; // #5273 - if (X(p==NULL, 0))
2018-10-26 06:21:45 +02:00
TEST_CASE ( ifelse10 ) ; // #8794 - if (!(x!=NULL))
2019-01-08 20:53:53 +01:00
TEST_CASE ( ifelse11 ) ; // #8365 - if (NULL == (p = malloc(4)))
2019-01-09 19:50:41 +01:00
TEST_CASE ( ifelse12 ) ; // #8340 - if ((*p = malloc(4)) == NULL)
2019-01-27 10:27:39 +01:00
TEST_CASE ( ifelse13 ) ; // #8392
2019-05-18 06:22:25 +02:00
TEST_CASE ( ifelse14 ) ; // #9130 - if (x == (char*)NULL)
2019-07-17 07:43:07 +02:00
TEST_CASE ( ifelse15 ) ; // #9206 - if (global_ptr = malloc(1))
2020-07-09 21:13:54 +02:00
TEST_CASE ( ifelse16 ) ; // #9635 - if (p = malloc(4), p == NULL)
2020-11-10 15:59:51 +01:00
TEST_CASE ( ifelse17 ) ; // if (!!(!p))
2021-01-11 07:55:05 +01:00
TEST_CASE ( ifelse18 ) ;
TEST_CASE ( ifelse19 ) ;
2021-02-26 12:58:52 +01:00
TEST_CASE ( ifelse20 ) ; // #10182
TEST_CASE ( ifelse21 ) ;
2021-03-03 07:00:28 +01:00
TEST_CASE ( ifelse22 ) ; // #10187
2022-02-15 12:52:10 +01:00
TEST_CASE ( ifelse23 ) ; // #5473
2022-02-16 21:31:24 +01:00
TEST_CASE ( ifelse24 ) ; // #1733
2022-05-27 07:57:43 +02:00
TEST_CASE ( ifelse25 ) ; // #9966
2022-05-28 00:11:23 +02:00
TEST_CASE ( ifelse26 ) ;
2022-07-24 12:15:04 +02:00
TEST_CASE ( ifelse27 ) ;
2022-11-03 10:37:43 +01:00
TEST_CASE ( ifelse28 ) ; // #11038
2012-05-26 08:53:46 +02:00
// switch
TEST_CASE ( switch1 ) ;
// loops
TEST_CASE ( loop1 ) ;
// mismatching allocation/deallocation
2016-10-09 10:28:19 +02:00
TEST_CASE ( mismatchAllocDealloc ) ;
2018-04-16 12:55:37 +02:00
2018-04-16 11:11:13 +02:00
TEST_CASE ( smartPointerDeleter ) ;
2018-05-05 18:06:49 +02:00
TEST_CASE ( smartPointerRelease ) ;
2012-05-26 08:53:46 +02:00
// Execution reaches a 'return'
TEST_CASE ( return1 ) ;
TEST_CASE ( return2 ) ;
TEST_CASE ( return3 ) ;
2012-06-01 19:08:50 +02:00
TEST_CASE ( return4 ) ;
2016-05-15 20:27:44 +02:00
TEST_CASE ( return5 ) ;
2019-07-26 07:03:58 +02:00
TEST_CASE ( return6 ) ; // #8282 return {p, p}
2019-09-20 15:09:27 +02:00
TEST_CASE ( return7 ) ; // #9343 return (uint8_t*)x
2019-09-22 19:18:31 +02:00
TEST_CASE ( return8 ) ;
2022-03-10 08:29:05 +01:00
TEST_CASE ( return9 ) ;
2012-05-26 08:53:46 +02:00
2012-06-01 19:01:19 +02:00
// General tests: variable type, allocation type, etc
TEST_CASE ( test1 ) ;
2012-06-20 17:09:41 +02:00
TEST_CASE ( test2 ) ;
2012-07-17 16:28:34 +02:00
TEST_CASE ( test3 ) ; // #3954 - reference pointer
2014-06-23 16:05:28 +02:00
TEST_CASE ( test4 ) ; // #5923 - static pointer
2014-10-14 16:40:30 +02:00
TEST_CASE ( test5 ) ; // unknown type
2012-06-01 19:01:19 +02:00
2012-09-22 10:37:27 +02:00
// Execution reaches a 'throw'
TEST_CASE ( throw1 ) ;
2016-05-13 14:53:32 +02:00
TEST_CASE ( throw2 ) ;
2012-09-22 10:37:27 +02:00
2012-05-26 08:53:46 +02:00
// Possible leak => Further configuration is needed for complete analysis
TEST_CASE ( configuration1 ) ;
TEST_CASE ( configuration2 ) ;
TEST_CASE ( configuration3 ) ;
TEST_CASE ( configuration4 ) ;
2022-07-19 20:41:18 +02:00
TEST_CASE ( configuration5 ) ;
2023-01-26 22:29:49 +01:00
TEST_CASE ( configuration6 ) ;
2012-08-26 11:39:17 +02:00
TEST_CASE ( ptrptr ) ;
2014-09-30 13:02:02 +02:00
TEST_CASE ( nestedAllocation ) ;
2015-06-14 15:49:49 +02:00
TEST_CASE ( testKeywords ) ; // #6767
2016-05-26 17:42:27 +02:00
TEST_CASE ( inlineFunction ) ; // #3989
2018-05-14 13:08:33 +02:00
2018-05-14 22:48:37 +02:00
TEST_CASE ( smartPtrInContainer ) ; // #8262
2019-07-12 07:56:05 +02:00
2020-07-07 23:46:24 +02:00
TEST_CASE ( functionCallCastConfig ) ; // #9652
2022-04-28 19:50:16 +02:00
TEST_CASE ( functionCallLeakIgnoreConfig ) ; // #7923
2012-05-26 08:53:46 +02:00
}
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 [ ] , bool cpp = false ) {
2012-05-26 08:53:46 +02:00
// Clear the error buffer..
errout . str ( " " ) ;
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , cpp ? " test.cpp " : " test.c " ) , file , line ) ;
2014-10-14 16:40:30 +02:00
settings . checkLibrary = true ;
2023-01-29 17:23:03 +01:00
// Check for leaks..
runChecks < CheckLeakAutoVar > ( & tokenizer , & settings , this ) ;
2014-10-14 16:40:30 +02:00
}
2021-11-29 07:34:39 +01:00
void check_ ( const char * file , int line , const char code [ ] , Settings & settings_ ) {
2020-07-07 23:46:24 +02:00
// Clear the error buffer..
errout . str ( " " ) ;
// Tokenize..
2021-07-16 21:55:12 +02:00
Tokenizer tokenizer ( & settings_ , this ) ;
2020-07-07 23:46:24 +02:00
std : : istringstream istr ( code ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , " test.cpp " ) , file , line ) ;
2020-07-07 23:46:24 +02:00
2021-07-16 21:55:12 +02:00
settings_ . checkLibrary = true ;
2023-01-29 17:23:03 +01:00
// Check for leaks..
runChecks < CheckLeakAutoVar > ( & tokenizer , & settings_ , this ) ;
2020-07-07 23:46:24 +02:00
}
2014-11-20 14:20:09 +01:00
void assign1 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" p = NULL; \n "
" free(p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-06-30 16:23:10 +02:00
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void assign2 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" char *q = p; \n "
" free(q); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 08:53:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign3 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" char *q = p + 1; \n "
" free(q - 1); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 08:53:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign4 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *a = malloc(10); \n "
" a += 10; \n "
" free(a - 10); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 08:53:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign5 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void foo() \n "
" { \n "
" char *p = new char[100]; \n "
" list += p; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 08:53:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign6 ( ) { // #2806 - FP when there is redundant assignment
2012-05-26 08:53:46 +02:00
check ( " void foo() { \n "
" char *p = malloc(10); \n "
" p = strcpy(p,q); \n "
" free(p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 08:53:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign7 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void foo(struct str *d) { \n "
" struct str *p = malloc(10); \n "
" d->p = p; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 08:53:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign8 ( ) { // linux list
2012-05-26 08:53:46 +02:00
check ( " void foo(struct str *d) { \n "
" struct str *p = malloc(10); \n "
" d->p = &p->x; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 08:53:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign9 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void foo() { \n "
" char *p = x(); \n "
" free(p); \n "
" p = NULL; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 08:53:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign10 ( ) {
2012-05-26 21:28:35 +02:00
check ( " void foo() { \n "
" char *p; \n "
" if (x) { p = malloc(10); } \n "
" if (!x) { p = NULL; } \n "
" free(p); \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 21:28:35 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign11 ( ) { // #3942 - FP for x = a(b(p));
2012-08-21 17:02:11 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" x = a(b(p)); \n "
" } " ) ;
2015-02-03 18:35:52 +01:00
ASSERT_EQUALS ( " [test.c:4]: (information) --check-library: Function b() should have <use>/<leak-ignore> configuration \n " , errout . str ( ) ) ;
2012-08-21 17:02:11 +02:00
}
2014-11-20 14:20:09 +01:00
void assign12 ( ) { // #4236: FP. bar(&x)
2012-10-25 19:41:18 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" free(p); \n "
" bar(&p); \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void assign13 ( ) { // #4237: FP. char *&ref=p; p=malloc(10); free(ref);
2012-10-27 16:36:14 +02:00
check ( " void f() { \n "
" char *p; \n "
" char * &ref = p; \n "
" p = malloc(10); \n "
" free(ref); \n "
" } " ) ;
2021-02-20 13:02:14 +01:00
TODO_ASSERT_EQUALS ( " " , " [test.c:6]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2012-10-27 16:36:14 +02:00
}
2017-10-26 19:11:00 +02:00
void assign14 ( ) {
check ( " void f(int x) { \n "
" char *p; \n "
" if (x && (p = malloc(10))) { } "
" } " ) ;
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" char *p; \n "
" if (x && (p = new char[10])) { } "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2019-05-30 16:22:41 +02:00
void assign15 ( ) {
// #8120
check ( " void f() { \n "
" baz *p; \n "
" p = malloc(sizeof *p); \n "
" free(p); \n "
" p = malloc(sizeof *p); \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-06-02 15:25:45 +02:00
void assign16 ( ) {
check ( " void f() { \n "
" char *p = malloc(10); \n "
" free(p); \n "
" if (p=dostuff()) *p = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-07-03 08:39:44 +02:00
void assign17 ( ) { // #9047
check ( " void f() { \n "
" char *p = (char*)malloc(10); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" char *p = (char*)(int*)malloc(10); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
void assign18 ( ) {
check ( " void f(int x) { \n "
" char *p; \n "
" if (x && (p = (char*)malloc(10))) { } "
" } " ) ;
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" char *p; \n "
" if (x && (p = (char*)(int*)malloc(10))) { } "
" } " ) ;
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2019-07-10 09:13:59 +02:00
void assign19 ( ) {
check ( " void f() { \n "
" char *p = malloc(10); \n "
" free((void*)p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-02-22 21:26:26 +01:00
void assign20 ( ) { // #9187
check ( " void f() { \n "
" char *p = static_cast<int>(malloc(10)); \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2021-02-25 10:55:34 +01:00
void assign21 ( ) { // #10186
check ( " void f(int **x) { \n "
" void *p = malloc(10); \n "
2021-05-10 08:01:30 +02:00
" *x = (int*)p; \n "
2021-02-25 10:55:34 +01:00
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-03-03 06:58:38 +01:00
void assign22 ( ) { // #9139
check ( " void f(char tempFileName[256]) { \n "
" const int fd = socket(AF_INET, SOCK_PACKET, 0 ); \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Resource leak: fd \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" const void * const p = malloc(10); \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2022-05-01 15:46:07 +02:00
void assign23 ( ) {
Settings s = settings ;
LOAD_LIB_2 ( settings . library , " posix.cfg " ) ;
check ( " void f() { \n "
" int n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14; \n "
" *&n1 = open( \" xx.log \" , O_RDONLY); \n "
" *&(n2) = open( \" xx.log \" , O_RDONLY); \n "
" *(&n3) = open( \" xx.log \" , O_RDONLY); \n "
" *&*&n4 = open( \" xx.log \" , O_RDONLY); \n "
" *&*&*&(n5) = open( \" xx.log \" , O_RDONLY); \n "
" *&*&(*&n6) = open( \" xx.log \" , O_RDONLY); \n "
" *&*(&*&n7) = open( \" xx.log \" , O_RDONLY); \n "
" *(&*&n8) = open( \" xx.log \" , O_RDONLY); \n "
" *&(*&*&(*&n9)) = open( \" xx.log \" , O_RDONLY); \n "
" (n10) = open( \" xx.log \" , O_RDONLY); \n "
" ((n11)) = open( \" xx.log \" , O_RDONLY); \n "
" ((*&n12)) = open( \" xx.log \" , O_RDONLY); \n "
" *(&(*&n13)) = open( \" xx.log \" , O_RDONLY); \n "
" ((*&(*&n14))) = open( \" xx.log \" , O_RDONLY); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " [test.cpp:17]: (error) Resource leak: n1 \n "
" [test.cpp:17]: (error) Resource leak: n2 \n "
" [test.cpp:17]: (error) Resource leak: n3 \n "
" [test.cpp:17]: (error) Resource leak: n4 \n "
" [test.cpp:17]: (error) Resource leak: n5 \n "
" [test.cpp:17]: (error) Resource leak: n6 \n "
" [test.cpp:17]: (error) Resource leak: n7 \n "
" [test.cpp:17]: (error) Resource leak: n8 \n "
" [test.cpp:17]: (error) Resource leak: n9 \n "
" [test.cpp:17]: (error) Resource leak: n10 \n "
" [test.cpp:17]: (error) Resource leak: n11 \n "
" [test.cpp:17]: (error) Resource leak: n12 \n "
" [test.cpp:17]: (error) Resource leak: n13 \n "
" [test.cpp:17]: (error) Resource leak: n14 \n " ,
errout . str ( ) ) ;
settings = s ;
}
2022-06-25 08:38:17 +02:00
void assign24 ( ) { // #7440
check ( " void f() { \n "
" char* data = new char[100]; \n "
" char** dataPtr = &data; \n "
" delete[] *dataPtr; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" char* data = new char[100]; \n "
" char** dataPtr = &data; \n "
" printf( \" test \" ); \n "
" delete[] *dataPtr; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-07-17 08:59:09 +02:00
void isAutoDealloc ( ) {
check ( " void f() { \n "
" char *p = new char[100]; "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:2]: (error) Memory leak: p \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" Fred *fred = new Fred; "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" std::string *str = new std::string; "
" } " , true ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:2]: (error) Memory leak: str \n " , " " , errout . str ( ) ) ;
2019-11-10 08:28:46 +01:00
check ( " class TestType { \n " // #9028
" public: \n "
" char ca[12]; \n "
" }; \n "
" void f() { \n "
" TestType *tt = new TestType(); \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:7]: (error) Memory leak: tt \n " , errout . str ( ) ) ;
2021-11-29 22:51:35 +01:00
check ( " void f(Bar& b) { \n " // #7622
" char* data = new char[10]; \n "
" b = Bar(*new Foo(data)); \n "
" } " , /*cpp*/ true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (information) --check-library: Function Foo() should have <use>/<leak-ignore> configuration \n " , errout . str ( ) ) ;
2019-07-17 08:59:09 +02:00
}
2019-07-05 12:44:52 +02:00
void realloc1 ( ) {
check ( " void f() { \n "
" void *p = malloc(10); \n "
" void *q = realloc(p, 20); \n "
" free(q) \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void realloc2 ( ) {
check ( " void f() { \n "
" void *p = malloc(10); \n "
" void *q = realloc(p, 20); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:4]: (error) Memory leak: q \n " , errout . str ( ) ) ;
}
void realloc3 ( ) {
check ( " void f() { \n "
" char *p = malloc(10); \n "
" char *q = (char*) realloc(p, 20); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:4]: (error) Memory leak: q \n " , errout . str ( ) ) ;
}
2021-01-11 07:55:05 +01:00
void realloc4 ( ) {
check ( " void f(void *p) { \n "
" void * q = realloc(p, 10); \n "
" if (q == NULL) \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:5]: (error) Memory leak: q \n " , errout . str ( ) ) ;
}
void realloc5 ( ) {
// #9292
check ( " void * f(void * ptr, size_t size) { \n "
" void *datap = realloc(ptr, size); \n "
" if (size && !datap) \n "
" free(ptr); \n "
" return datap; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
// #9990
check ( " void f() { \n "
" void * p1 = malloc(10); \n "
" if (!p1) \n "
" return; \n "
" void * p2 = realloc(p1, 42); \n "
" if (!p2) { \n "
" free(p1); \n "
" return; \n "
" } \n "
" free(p2); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-07-05 12:44:52 +02:00
void freopen1 ( ) {
check ( " void f() { \n "
" void *p = fopen(name,a); \n "
" void *q = freopen(name, b, p); \n "
" fclose(q) \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
void freopen2 ( ) {
check ( " void f() { \n "
" void *p = fopen(name,a); \n "
" void *q = freopen(name, b, p); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:4]: (error) Resource leak: q \n " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void deallocuse1 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f(char *p) { \n "
" free(p); \n "
" *p = 0; \n "
" } " ) ;
2012-06-30 16:23:10 +02:00
ASSERT_EQUALS ( " [test.c:3]: (error) Dereferencing 'p' after it is deallocated / released \n " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
check ( " void f(char *p) { \n "
" free(p); \n "
" char c = *p; \n "
" } " ) ;
2012-06-30 16:23:10 +02:00
ASSERT_EQUALS ( " [test.c:3]: (error) Dereferencing 'p' after it is deallocated / released \n " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void deallocuse2 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f(char *p) { \n "
" free(p); \n "
" strcpy(a, p); \n "
" } " ) ;
2013-07-16 18:50:25 +02:00
TODO_ASSERT_EQUALS ( " error (free,use) " , " [test.c:3]: (information) --check-library: Function strcpy() should have <noreturn> configuration \n " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
check ( " void f(char *p) { \n " // #3041 - assigning pointer when it's used
" free(p); \n "
" strcpy(a, p=b()); \n "
" } " ) ;
2013-07-16 18:50:25 +02:00
TODO_ASSERT_EQUALS ( " " , " [test.c:3]: (information) --check-library: Function strcpy() should have <noreturn> configuration \n " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void deallocuse3 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f(struct str *p) { \n "
" free(p); \n "
" p = p->next; \n "
" } " ) ;
2012-06-30 16:23:10 +02:00
ASSERT_EQUALS ( " [test.c:3]: (error) Dereferencing 'p' after it is deallocated / released \n " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void deallocuse4 ( ) {
2012-06-11 18:28:31 +02:00
check ( " void f(char *p) { \n "
" free(p); \n "
" return p; \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:3]: (error) Returning/dereferencing 'p' after it is deallocated / released \n " , errout . str ( ) ) ;
2017-03-03 18:36:06 +01:00
check ( " void f(char *p) { \n "
" if (!p) free(p); \n "
" return p; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-04-24 22:05:16 +02:00
check ( " void f(char *p) { \n "
" if (!p) delete p; \n "
" return p; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *p) { \n "
" if (!p) delete [] p; \n "
" return p; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2019-09-20 15:09:27 +02:00
check ( " void f(void* p) { \n "
" if (a) { \n "
" free(p); \n "
" return; \n "
" } \n "
" g(p); \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-06-11 18:28:31 +02:00
}
2014-11-20 14:20:09 +01:00
void deallocuse5 ( ) { // #4018
2012-08-12 16:18:07 +02:00
check ( " void f(char *p) { \n "
" free(p), p = 0; \n "
" *p = 0; \n " // <- Make sure pointer info is reset. It is NOT a freed pointer dereference
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void deallocuse6 ( ) { // #4034
2012-08-28 06:38:38 +02:00
check ( " void f(char *p) { \n "
" free(p); \n "
" x = p = foo(); \n " // <- p is not dereferenced
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2015-07-19 17:37:50 +02:00
void deallocuse7 ( ) { // #6467, #6469, #6473, #6648
2015-01-29 10:18:21 +01:00
check ( " struct Foo { int* ptr; }; \n "
" void f(Foo* foo) { \n "
" delete foo->ptr; \n "
2021-02-20 12:58:42 +01:00
" foo->ptr = new Foo; \n "
2015-01-29 10:18:21 +01:00
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Foo { int* ptr; }; \n "
" void f(Foo* foo) { \n "
" delete foo->ptr; \n "
2021-02-20 12:58:42 +01:00
" x = *foo->ptr; \n "
2015-01-29 10:18:21 +01:00
" } " , true ) ;
2022-07-24 12:15:04 +02:00
TODO_ASSERT_EQUALS ( " [test.cpp:4]: (error) Dereferencing 'ptr' after it is deallocated / released \n " , " " , errout . str ( ) ) ;
2015-01-29 21:26:06 +01:00
check ( " void parse() { \n "
" struct Buf { \n "
" Buf(uint32_t len) : m_buf(new uint8_t[len]) {} \n "
" ~Buf() { delete[]m_buf; } \n "
" uint8_t *m_buf; \n "
" }; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct Foo { \n "
" Foo(); \n "
" Foo* ptr; \n "
" void func(); \n "
" }; \n "
" void bar(Foo* foo) { \n "
" delete foo->ptr; \n "
" foo->ptr = new Foo; \n "
" foo->ptr->func(); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-07-19 17:37:50 +02:00
check ( " void foo(void (*conv)(char**)) { \n "
" char * ptr=(char*)malloc(42); \n "
" free(ptr); \n "
" (*conv)(&ptr); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-01-29 10:18:21 +01:00
}
2019-07-12 18:25:04 +02:00
void deallocuse8 ( ) { // #1765
check ( " void f() { \n "
" int *ptr = new int; \n "
" delete(ptr); \n "
" *ptr = 0; \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Dereferencing 'ptr' after it is deallocated / released \n " , errout . str ( ) ) ;
}
2022-02-02 19:30:49 +01:00
void deallocuse9 ( ) {
check ( " void f(Type* p) { \n " // #9781
2022-01-19 21:39:45 +01:00
" std::shared_ptr<Type> sp(p); \n "
" bool b = p->foo(); \n "
" return b; \n "
" } \n " , /*cpp*/ true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-02-02 19:30:49 +01:00
check ( " struct A { \n " // #8635
" std::vector<std::unique_ptr<A>> array_; \n "
" A* foo() { \n "
" A* a = new A(); \n "
" array_.push_back(std::unique_ptr<A>(a)); \n "
" return a; \n "
" } \n "
" }; \n " , /*cpp*/ true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-04-28 15:24:54 +02:00
check ( " int g(int *p) { \n " // #9838
" std::unique_ptr<int> temp(p); \n "
" return DoSomething(p); \n "
" } \n "
" int f() { \n "
" return g(new int(3)); \n "
" } \n " , /*cpp*/ true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-01-19 21:39:45 +01:00
}
2014-11-20 14:20:09 +01:00
void doublefree1 ( ) { // #3895
2012-06-22 09:10:30 +02:00
check ( " void f(char *p) { \n "
" if (x) \n "
" free(p); \n "
" else \n "
" p = 0; \n "
" free(p); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:3] -> [test.c:6]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(char *p) { \n "
" free(p); \n "
" free(p); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:3]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(char *p, char *r) { \n "
" free(p); \n "
" free(r); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo() { \n "
" free(p); \n "
" free(r); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(char *p) { \n "
" if (x < 3) free(p); \n "
" else { if (x > 9) free(p); } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(char *p) { \n "
" free(p); \n "
" getNext(&p); \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(char *p) { \n "
" free(p); \n "
" bar(); \n "
" free(p); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:4]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(char *p) { \n "
" free(p); \n "
" printf( \" Freed memory at location %x \" , p); \n "
" free(p); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:4]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(FILE *p) { \n "
" fclose(p); \n "
" fclose(p); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:3]: (error) Resource handle 'p' freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(FILE *p, FILE *r) { \n "
" fclose(p); \n "
" fclose(r); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(FILE *p) { \n "
" if (x < 3) fclose(p); \n "
" else { if (x > 9) fclose(p); } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(FILE *p) { \n "
" fclose(p); \n "
" gethandle(&p); \n "
" fclose(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(FILE *p) { \n "
" fclose(p); \n "
" gethandle(); \n "
" fclose(p); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:4]: (error) Resource handle 'p' freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(Data* p) { \n "
" free(p->a); \n "
" free(p->b); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void f() { \n "
" char *p; p = malloc(100); \n "
" if (x) { \n "
" free(p); \n "
" exit(); \n "
" } \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void f() { \n "
" char *p; p = malloc(100); \n "
" if (x) { \n "
" free(p); \n "
" x = 0; \n "
" } \n "
" free(p); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:4] -> [test.c:7]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void f() { \n "
" char *p; p = do_something(); \n "
" free(p); \n "
" p = do_something(); \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(char *p) { \n "
" delete p; \n "
" delete p; \n "
" } " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(char *p, char *r) { \n "
" delete p; \n "
" delete r; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(P p) { \n "
" delete p.x; \n "
" delete p; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-01-29 09:50:33 +01:00
check (
" void foo(char **p) { \n "
" delete p[0]; \n "
" delete p[1]; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(char *p) { \n "
" delete p; \n "
" getNext(&p); \n "
" delete p; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(char *p) { \n "
" delete p; \n "
" bar(); \n "
" delete p; \n "
" } " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(char *p) { \n "
" delete[] p; \n "
" delete[] p; \n "
" } " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(char *p, char *r) { \n "
" delete[] p; \n "
" delete[] r; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(char *p) { \n "
" delete[] p; \n "
" getNext(&p); \n "
" delete[] p; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(char *p) { \n "
" delete[] p; \n "
" bar(); \n "
" delete[] p; \n "
" } " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:4]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
2016-11-20 17:59:50 +01:00
" LineMarker::~LineMarker() { \n "
2015-01-28 13:45:40 +01:00
" delete pxpm; \n "
" } \n "
2016-11-20 17:59:50 +01:00
" LineMarker &LineMarker::operator=(const LineMarker &) { \n "
2015-01-28 13:45:40 +01:00
" delete pxpm; \n "
" pxpm = NULL; \n "
" return *this; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo() \n "
" { \n "
" int* ptr; ptr = NULL; \n "
" try \n "
" { \n "
" ptr = new int(4); \n "
" } \n "
" catch(...) \n "
" { \n "
" delete ptr; \n "
" throw; \n "
" } \n "
" delete ptr; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" int foo() \n "
" { \n "
" int* a; a = new int; \n "
" bool doDelete; doDelete = true; \n "
" if (a != 0) \n "
" { \n "
" doDelete = false; \n "
" delete a; \n "
" } \n "
" if(doDelete) \n "
" delete a; \n "
" return 0; \n "
" } " , true ) ;
2019-09-22 21:50:02 +02:00
TODO_ASSERT_EQUALS ( " " , " [test.cpp:8] -> [test.cpp:11]: (error) Memory pointed to by 'a' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void foo(int y) \n "
" { \n "
" char * x; x = NULL; \n "
" while(true) { \n "
" x = new char[100]; \n "
" if (y++ > 100) \n "
" break; \n "
" delete[] x; \n "
" } \n "
" delete[] x; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(int y) \n "
" { \n "
" char * x; x = NULL; \n "
" for (int i = 0; i < 10000; i++) { \n "
" x = new char[100]; \n "
" delete[] x; \n "
" } \n "
" delete[] x; \n "
" } " , true ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory pointed to by 'x' is freed twice. \n " , " " , errout . str ( ) ) ;
check (
" void foo(int y) \n "
" { \n "
" char * x; x = NULL; \n "
" while (isRunning()) { \n "
" x = new char[100]; \n "
" delete[] x; \n "
" } \n "
" delete[] x; \n "
" } " , true ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:8]: (error) Memory pointed to by 'x' is freed twice. \n " , " " , errout . str ( ) ) ;
check (
" void foo(int y) \n "
" { \n "
" char * x; x = NULL; \n "
" while (isRunning()) { \n "
" x = malloc(100); \n "
" free(x); \n "
" } \n "
" free(x); \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " [test.c:8]: (error) Memory pointed to by 'x' is freed twice. \n " , " " , errout . str ( ) ) ;
check (
" void foo(int y) \n "
" { \n "
" char * x; x = NULL; \n "
" for (;;) { \n "
" x = new char[100]; \n "
" if (y++ > 100) \n "
" break; \n "
" delete[] x; \n "
" } \n "
" delete[] x; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void foo(int y) \n "
" { \n "
" char * x; x = NULL; \n "
" do { \n "
" x = new char[100]; \n "
" if (y++ > 100) \n "
" break; \n "
" delete[] x; \n "
" } while (true); \n "
" delete[] x; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void f() \n "
" { \n "
" char *p; p = 0; \n "
" if (x < 100) { \n "
" p = malloc(10); \n "
" free(p); \n "
" } \n "
" free(p); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:6] -> [test.c:8]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2015-01-28 13:45:40 +01:00
check (
" void MyFunction() \n "
" { \n "
" char* data; data = new char[100]; \n "
" try \n "
" { \n "
" } \n "
" catch(err) \n "
" { \n "
" delete[] data; \n "
" MyThrow(err); \n "
" } \n "
" delete[] data; \n "
" } \n "
" void MyThrow(err) \n "
" { \n "
" throw(err); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check (
" void MyFunction() \n "
" { \n "
" char* data; data = new char[100]; \n "
" try \n "
" { \n "
" } \n "
" catch(err) \n "
" { \n "
" delete[] data; \n "
" MyExit(err); \n "
" } \n "
" delete[] data; \n "
" } \n "
" void MyExit(err) \n "
" { \n "
" exit(err); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( // #6252
" struct Wrapper { \n "
" Thing* m_thing; \n "
" Wrapper() : m_thing(0) { \n "
" } \n "
" ~Wrapper() { \n "
" delete m_thing; \n "
" } \n "
" void changeThing() { \n "
" delete m_thing; \n "
" m_thing = new Thing; \n "
" } \n "
" }; " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2016-05-04 12:14:42 +02:00
// #7401
check ( " void pCodeLabelDestruct(pCode *pc) { \n "
" free(PCL(pc)->label); \n "
" free(pc); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-06-22 09:10:30 +02:00
}
2014-11-20 14:20:09 +01:00
void doublefree2 ( ) { // #3891
2012-07-16 17:07:51 +02:00
check ( " void *f(int a) { \n "
" char *p = malloc(10); \n "
" if (a == 2) { free(p); return ((void*)1); } \n "
" free(p); \n "
" return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2013-07-28 11:53:49 +02:00
2014-11-20 14:20:09 +01:00
void doublefree3 ( ) { // #4914
2013-07-28 10:26:46 +02:00
check ( " void foo() { \n "
" bool done = false; \n "
" do { \n "
" char *bar = malloc(10) \n "
" if(condition()) { \n "
" free(bar); \n "
" continue; \n "
" } \n "
" done = true; \n "
" free(bar) \n "
" } while(!done); \n "
" return; "
" } "
2021-08-07 20:51:18 +02:00
) ;
2013-07-28 10:26:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-05-04 12:02:55 +02:00
}
2022-11-19 16:49:34 +01:00
void doublefree4 ( ) {
check ( " void f(char *p) { \n " // #5451 - exit
2014-05-04 13:11:21 +02:00
" if (x) { \n "
" free(p); \n "
" exit(1); \n "
" } \n "
" free(p); \n "
2014-05-04 12:02:55 +02:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-11-19 16:49:34 +01:00
check ( " void f(void* p, int i) { \n " // #11391
" if (i) \n "
" goto cleanup; \n "
" free(p); \n "
" exit(0); \n "
" cleanup: \n "
" free(p); \n "
" exit(1); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2013-07-28 10:26:46 +02:00
}
2012-07-16 17:07:51 +02:00
2016-05-26 19:21:45 +02:00
void doublefree5 ( ) { // #5522
check ( " void f(char *p) { \n "
" free(p); \n "
" x = (q == p); \n "
" free(p); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:4]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
2016-05-26 19:21:45 +02:00
}
2016-12-29 13:17:46 +01:00
void doublefree6 ( ) { // #7685
check ( " void do_wordexp(FILE *f) { \n "
" free(getword(f)); \n "
" fclose(f); \n "
2021-08-07 20:51:18 +02:00
" } " , /*cpp=*/ false ) ;
2016-12-29 13:17:46 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2017-10-26 19:11:00 +02:00
void doublefree7 ( ) {
check ( " void f(char *p, int x) { \n "
" free(p); \n "
" if (x && (p = malloc(10))) \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *p, int x) { \n "
" delete[] p; \n "
" if (x && (p = new char[10])) \n "
" delete[] p; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-04-16 11:11:13 +02:00
void doublefree8 ( ) {
check ( " void f() { \n "
" int * i = new int; \n "
" std::unique_ptr<int> x(i); \n "
" delete i; \n "
" } \n " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice. \n " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
check ( " void f() { \n "
" int * i = new int; \n "
" delete i; \n "
" std::unique_ptr<int> x(i); \n "
" } \n " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice. \n " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
check ( " void f() { \n "
" int * i = new int; \n "
" std::unique_ptr<int> x{i}; \n "
" delete i; \n "
" } \n " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice. \n " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
check ( " void f() { \n "
" int * i = new int; \n "
" std::shared_ptr<int> x(i); \n "
" delete i; \n "
" } \n " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice. \n " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
check ( " void f() { \n "
" int * i = new int; \n "
" std::shared_ptr<int> x{i}; \n "
" delete i; \n "
" } \n " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice. \n " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
// Check for use-after-free FP
check ( " void f() { \n "
" int * i = new int; \n "
" std::shared_ptr<int> x{i}; \n "
" *i = 123; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int * i = new int[1]; \n "
" std::unique_ptr<int[]> x(i); \n "
" delete i; \n "
" } \n " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:3] -> [test.cpp:4]: (error) Memory pointed to by 'i' is freed twice. \n " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
}
2018-04-21 11:24:19 +02:00
void doublefree9 ( ) {
2018-04-21 13:28:31 +02:00
check ( " struct foo { \n "
" int* get(int) { return new int(); } \n "
" }; \n "
" void f(foo* b) { \n "
" std::unique_ptr<int> x(b->get(0)); \n "
" std::unique_ptr<int> y(b->get(1)); \n "
" } \n " , true ) ;
2018-04-21 11:24:19 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-08-07 08:04:10 +02:00
void doublefree10 ( ) {
check ( " void f(char* s) { \n "
2019-08-07 08:05:46 +02:00
" char *p = malloc(strlen(s)); \n "
" if (p != NULL) { \n "
" strcat(p, s); \n "
" if (strlen(s) != 10) \n "
2019-08-07 08:04:10 +02:00
" free(p); p = NULL; \n "
2019-08-07 08:05:46 +02:00
" } \n "
" if (p != NULL) \n "
2019-08-07 08:04:10 +02:00
" free(p); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char* s) { \n "
2019-08-07 08:05:46 +02:00
" char *p = malloc(strlen(s)); \n "
" if (p != NULL) { \n "
" strcat(p, s); \n "
" if (strlen(s) != 10) \n "
2019-08-07 08:04:10 +02:00
" free(p), p = NULL; \n "
2019-08-07 08:05:46 +02:00
" } \n "
" if (p != NULL) \n "
2019-08-07 08:04:10 +02:00
" free(p); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-01-11 07:55:05 +01:00
void doublefree11 ( ) {
check ( " void f() { \n "
" void * p = malloc(5); \n "
" void * q = realloc(p, 10); \n "
" if (q == NULL) { \n "
" free(p); \n "
" return; \n "
" } \n "
" free(p); \n "
" if (q == NULL) \n "
" return; \n "
" free(q) \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:3] -> [test.c:8]: (error) Memory pointed to by 'p' is freed twice. \n " , errout . str ( ) ) ;
}
2022-03-21 22:17:50 +01:00
void doublefree12 ( ) { // #10502
check ( " int f(FILE *fp, const bool b) { \n "
" if (b) \n "
" return fclose(fp); \n "
" fclose(fp); \n "
" return 0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2022-07-19 20:41:08 +02:00
void doublefree13 ( ) { // #11008
check ( " struct buf_t { void* ptr; }; \n "
" void f() { \n "
" struct buf_t buf; \n "
" if ((buf.ptr = malloc(10)) == NULL) \n "
" return; \n "
" free(buf.ptr); \n "
" if ((buf.ptr = malloc(10)) == NULL) \n "
" return; \n "
" free(buf.ptr); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void exit1 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" exit(0); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void exit2 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" fatal_error(); \n "
" } " ) ;
2013-07-16 18:50:25 +02:00
ASSERT_EQUALS ( " [test.c:3]: (information) --check-library: Function fatal_error() should have <noreturn> configuration \n "
2015-02-03 18:35:52 +01:00
" [test.c:4]: (information) --check-library: Function fatal_error() should have <use>/<leak-ignore> configuration \n " ,
2013-07-16 18:50:25 +02:00
errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2017-02-25 11:36:48 +01:00
void exit3 ( ) {
check ( " void f() { \n "
" char *p = malloc(100); \n "
" if (x) { \n "
" free(p); \n "
" ::exit(0); \n "
" } "
" free(p); \n "
2017-04-06 08:50:35 +02:00
" } " , true ) ;
2017-02-25 11:36:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" char *p = malloc(100); \n "
" if (x) { \n "
" free(p); \n "
" std::exit(0); \n "
" } "
" free(p); \n "
2017-04-06 08:50:35 +02:00
" } " , true ) ;
2017-02-25 11:36:48 +01:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2017-07-07 21:51:48 +02:00
void functioncall1 ( ) {
check ( " void f(struct S *p) { \n "
" p->x = malloc(10); \n "
" free(p->x); \n "
" p->x = 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-07-26 11:14:35 +02:00
check ( " void f(s_t s) { \n " // #11061
" s->p = (char*)malloc(10); \n "
" free((void*)s->p); \n "
" s->p = NULL; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-07-07 21:51:48 +02:00
}
2014-11-20 14:20:09 +01:00
void goto1 ( ) {
2012-05-26 08:53:46 +02:00
check ( " static void f() { \n "
" int err = -ENOMEM; \n "
" char *reg = malloc(100); \n "
" if (err) { \n "
" free(reg); \n "
" } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void goto2 ( ) { // #4231
2012-10-08 17:23:47 +02:00
check ( " static char * f() { \n "
" x: \n "
" char *p = malloc(100); \n "
" if (err) { \n "
" free(p); \n "
" goto x; \n "
" } \n "
" return p; \n " // no error since there is a goto
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2022-12-14 22:47:14 +01:00
void goto3 ( ) { // #11431
check ( " void f() { \n "
" int* p = (int*)malloc(2); \n "
" if (!p) { \n "
" p = (int*)malloc(1); \n "
" if (!p) \n "
" goto err; \n "
" } \n "
" free(p); \n "
" err: \n "
" (void)0; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void ifelse1 ( ) {
2012-05-26 08:53:46 +02:00
check ( " int f() { \n "
" char *p = NULL; \n "
" if (x) { p = malloc(10); } \n "
" else { return 0; } \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void ifelse2 ( ) {
2012-05-26 08:53:46 +02:00
check ( " int f() { \n "
" char *p = NULL; \n "
" if (x) { p = malloc(10); } \n "
" else { return 0; } \n "
" } " ) ;
2012-06-30 16:23:10 +02:00
ASSERT_EQUALS ( " [test.c:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void ifelse3 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" if (!p) { return; } \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-07-25 11:37:03 +02:00
check ( " char * f(size_t size) { "
" void *p = malloc(1); "
" if (!p && size != 0) "
" return NULL; "
" return p; "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" if (p) { } else { return; } \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-06-17 07:54:24 +02:00
// #3866 - UNLIKELY
check ( " void f() { \n "
" char *p = malloc(10); \n "
" if (UNLIKELY(!p)) { return; } \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void ifelse4 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f(int x) { \n "
" char *p; \n "
" if (x) { p = malloc(10); } \n "
" if (x) { free(p); } \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(int x) { \n "
" char *p; \n "
" if (x) { p = malloc(10); } \n "
" if (!x) { return; } \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void ifelse5 ( ) {
2012-05-29 21:10:19 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" if (!p && x) { p = malloc(10); } \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void ifelse6 ( ) { // #3370
2012-06-04 21:21:14 +02:00
check ( " void f(int x) { \n "
" int *a = malloc(20); \n "
" if (x) \n "
2012-06-06 13:37:56 +02:00
" free(a); \n "
2012-06-04 21:21:14 +02:00
" else \n "
2012-06-06 13:37:56 +02:00
" a = 0; \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-06-30 16:23:10 +02:00
ASSERT_EQUALS ( " [test.c:6]: (error) Memory leak: a \n " , errout . str ( ) ) ;
2012-06-04 21:21:14 +02:00
}
2014-11-20 14:20:09 +01:00
void ifelse7 ( ) { // #5576
2014-04-18 18:18:47 +02:00
check ( " void f() { \n "
" int x = malloc(20); \n "
" if (x < 0) \n " // assume negative value indicates its unallocated
" return; \n "
" free(x); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void ifelse8 ( ) { // #5747
2020-10-29 13:17:33 +01:00
check ( " int f() { \n "
2014-09-17 18:37:41 +02:00
" int fd = socket(AF_INET, SOCK_PACKET, 0 ); \n "
" if (fd == -1) \n "
2020-10-29 13:17:33 +01:00
" return -1; \n "
2020-10-29 21:43:56 +01:00
" return fd; \n "
2020-10-29 13:17:33 +01:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f() { \n "
" int fd = socket(AF_INET, SOCK_PACKET, 0 ); \n "
" if (fd != -1) \n "
" return fd; \n "
2020-10-29 21:43:56 +01:00
" return -1; \n "
2014-09-17 18:37:41 +02:00
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2017-06-30 23:05:09 +02:00
void ifelse9 ( ) { // #5273
check ( " void f() { \n "
" char *p = malloc(100); \n "
" if (dostuff(p==NULL,0)) \n "
" return; \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2018-10-26 06:21:45 +02:00
void ifelse10 ( ) { // #8794
check ( " void f() { \n "
" void *x = malloc(1U); \n "
" if (!(x != NULL)) \n "
" return; \n "
" free(x); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-01-08 20:53:53 +01:00
void ifelse11 ( ) { // #8365
check ( " void f() { \n "
" void *p; \n "
" if (NULL == (p = malloc(4))) \n "
" return; \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-01-09 19:50:41 +01:00
void ifelse12 ( ) { // #8340
check ( " void f(char **p) { \n "
" if ((*p = malloc(4)) == NULL) \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-01-27 10:27:39 +01:00
void ifelse13 ( ) { // #8392
check ( " int f(int fd, const char *mode) { \n "
" char *path; \n "
" if (fd == -1 || (path = (char *)malloc(10)) == NULL) \n "
" return 1; \n "
" free(path); \n "
" return 0; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(int fd, const char *mode) { \n "
" char *path; \n "
" if ((path = (char *)malloc(10)) == NULL || fd == -1) \n "
" return 1; \n " // <- memory leak
" free(path); \n "
" return 0; \n "
" } " ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:4] memory leak " , " " , errout . str ( ) ) ;
}
2019-05-18 06:22:25 +02:00
void ifelse14 ( ) { // #9130
check ( " char* f() { \n "
" char* buf = malloc(10); \n "
" if (buf == (char*)NULL) \n "
" return NULL; \n "
" return buf; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-07-17 07:43:07 +02:00
void ifelse15 ( ) { // #9206
check ( " struct SSS { int a; }; \n "
" SSS* global_ptr; \n "
" void test_alloc() { \n "
" if ( global_ptr = new SSS()) {} \n "
" return; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " FILE* hFile; \n "
" int openFile( void ) { \n "
" if ((hFile = fopen( \" 1.txt \" , \" wb \" )) == NULL) return 0; \n "
" return 1; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-07-09 21:13:54 +02:00
void ifelse16 ( ) { // #9635
check ( " void f(void) { \n "
" char *p; \n "
" if(p = malloc(4), p == NULL) \n "
" return; \n "
" free(p); \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(void) { \n "
" char *p, q; \n "
" if(p = malloc(4), q = 1, p == NULL) \n "
" return; \n "
" free(p); \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-11-10 15:59:51 +01:00
void ifelse17 ( ) {
check ( " int *f() { \n "
" int *p = realloc(nullptr, 10); \n "
" if (!p) \n "
" return NULL; \n "
" return p; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int *f() { \n "
" int *p = realloc(nullptr, 10); \n "
" if (!!(!p)) \n "
" return NULL; \n "
" return p; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-01-11 07:55:05 +01:00
void ifelse18 ( ) {
check ( " void f() { \n "
" void * p = malloc(10); \n "
" void * q = realloc(p, 20); \n "
" if (q == 0) \n "
" return; \n "
" free(q); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:5]: (error) Memory leak: p \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" void * p = malloc(10); \n "
" void * q = realloc(p, 20); \n "
" if (q != 0) { \n "
" free(q); \n "
" return; \n "
" } else \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:8]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
void ifelse19 ( ) {
check ( " void f() { \n "
" static char * a; \n "
" char * b = realloc(a, 10); \n "
" if (!b) \n "
" return; \n "
" a = b; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2021-02-26 12:58:52 +01:00
void ifelse20 ( ) {
check ( " void f() { \n "
" if (x > 0) \n "
" void * p1 = malloc(5); \n "
" else \n "
" void * p2 = malloc(2); \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p1 \n "
" [test.c:5]: (error) Memory leak: p2 \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" if (x > 0) \n "
" void * p1 = malloc(5); \n "
" else \n "
" void * p2 = malloc(2); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p1 \n "
" [test.c:5]: (error) Memory leak: p2 \n " , errout . str ( ) ) ;
}
void ifelse21 ( ) {
check ( " void f() { \n "
" if (y) { \n "
" void * p; \n "
" if (x > 0) \n "
" p = malloc(5); \n "
" } \n "
" return; \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:6]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2021-03-03 07:00:28 +01:00
void ifelse22 ( ) { // #10187
check ( " int f(const char * pathname, int flags) { \n "
" int fd = socket(pathname, flags); \n "
" if (fd >= 0) \n "
" return fd; \n "
" return -1; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int f(const char * pathname, int flags) { \n "
" int fd = socket(pathname, flags); \n "
" if (fd <= -1) \n "
" return -1; \n "
" return fd; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2022-02-15 12:52:10 +01:00
void ifelse23 ( ) { // #5473
check ( " void f() { \n "
" if (FILE* fp = fopen( \" x \" , \" r \" )) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " [test.c:2]: (error) Resource leak: fp \n " , errout . str ( ) ) ;
}
2022-02-16 21:31:24 +01:00
void ifelse24 ( ) { // #1733
Settings s ;
LOAD_LIB_2 ( s . library , " std.cfg " ) ;
LOAD_LIB_2 ( s . library , " posix.cfg " ) ;
check ( " void f() { \n "
" char* temp = strdup( \" temp.txt \" ); \n "
" FILE* fp; \n "
" if (NULL == x || NULL == (fp = fopen(temp, \" rt \" ))) \n "
" return; \n "
" } \n " , s ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: temp \n "
" [test.cpp:6]: (error) Memory leak: temp \n "
" [test.cpp:6]: (error) Resource leak: fp \n " ,
errout . str ( ) ) ;
check ( " FILE* f() { \n "
" char* temp = strdup( \" temp.txt \" ); \n "
" FILE* fp = fopen(temp, \" rt \" ); \n "
" return fp; \n "
" } \n " , s ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: temp \n " , errout . str ( ) ) ;
check ( " FILE* f() { \n "
2022-02-17 16:22:30 +01:00
" char* temp = strdup( \" temp.txt \" ); \n "
" FILE* fp = NULL; \n "
" fopen_s(&fp, temp, \" rt \" ); \n "
" return fp; \n "
" } \n " , s ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: temp \n " , errout . str ( ) ) ;
check ( " void f() { \n "
" char* temp = strdup( \" temp.txt \" ); \n "
" FILE* fp = fopen( \" a.txt \" , \" rb \" ); \n "
" if (fp) \n "
" freopen(temp, \" rt \" , fp); \n "
" } \n " , s ) ;
ASSERT_EQUALS ( " [test.cpp:6]: (error) Memory leak: temp \n "
" [test.cpp:6]: (error) Resource leak: fp \n " ,
errout . str ( ) ) ;
check ( " FILE* f() { \n "
2022-02-16 21:31:24 +01:00
" char* temp = strdup( \" temp.txt \" ); \n "
" return fopen(temp, \" rt \" ); \n "
" } \n " , s ) ;
TODO_ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: temp \n " , " " , errout . str ( ) ) ;
}
2022-05-27 07:57:43 +02:00
void ifelse25 ( ) { // #9966
check ( " void f() { \n "
" void *p, *p2; \n "
" if((p2 = p = malloc(10)) == NULL) \n "
" return; \n "
" (void)p; \n "
" free(p2); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2022-05-28 00:11:23 +02:00
void ifelse26 ( ) { // don't crash
check ( " union tidi { \n "
" long long ti; \n "
" unsigned int di[2]; \n "
" }; \n "
" void f(long long val) { \n "
" if (val == ({ union tidi d = {.di = {0x0, 0x80000000}}; d.ti; })) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2022-07-24 12:15:04 +02:00
void ifelse27 ( ) {
check ( " struct key { void* p; }; \n "
" int f(struct key** handle) { \n "
" struct key* key; \n "
" if (!(key = calloc(1, sizeof(*key)))) \n "
" return 0; \n "
" if (!(key->p = malloc(4))) { \n "
" free(key); \n "
" return 0; \n "
" } \n "
" *handle = key; \n "
" return 1; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2022-11-03 10:37:43 +01:00
void ifelse28 ( ) { // #11038
check ( " char * f(void) { \n "
" char *buf = (char*)malloc(42*sizeof(char)); \n "
" char *temp; \n "
" if ((temp = (char*)realloc(buf, 16)) != NULL) \n "
" { buf = temp; } \n "
" return buf; \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void switch1 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *p = 0; \n "
" switch (x) { \n "
" case 123: p = malloc(100); break; \n "
" default: return; \n "
" } \n "
" free(p); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void loop1 ( ) {
2012-05-26 08:53:46 +02:00
// test the handling of { }
check ( " void f() { \n "
" char *p; \n "
" for (i=0;i<5;i++) { } \n "
" if (x) { free(p) } \n "
" else { a = p; } \n "
2013-03-20 15:36:16 +01:00
" } " ) ;
2012-05-26 08:53:46 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2016-10-09 10:28:19 +02:00
void mismatchAllocDealloc ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" FILE*f=fopen(fname,a); \n "
" free(f); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:3]: (error) Mismatching allocation and deallocation: f \n " , errout . str ( ) ) ;
2016-10-09 10:28:19 +02:00
2019-07-10 09:13:59 +02:00
check ( " void f() { \n "
" FILE*f=fopen(fname,a); \n "
" free((void*)f); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:3]: (error) Mismatching allocation and deallocation: f \n " , errout . str ( ) ) ;
2019-07-10 09:13:59 +02:00
2016-10-09 10:28:19 +02:00
check ( " void f() { \n "
" char *cPtr = new char[100]; \n "
" delete[] cPtr; \n "
" cPtr = new char[100]('x'); \n "
" delete[] cPtr; \n "
" cPtr = new char[100]; \n "
" delete cPtr; \n "
" } " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:6] -> [test.cpp:7]: (error) Mismatching allocation and deallocation: cPtr \n " , errout . str ( ) ) ;
2016-10-09 10:28:19 +02:00
check ( " void f() { \n "
" char *cPtr = new char[100]; \n "
" free(cPtr); \n "
" } " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: cPtr \n " , errout . str ( ) ) ;
2017-05-04 19:39:57 +02:00
check ( " void f() { \n "
" char *cPtr = new (buf) char[100]; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
check ( " void f() { \n "
" int * i = new int[1]; \n "
" std::unique_ptr<int> x(i); \n "
" } \n " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: i \n " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
check ( " void f() { \n "
" int * i = new int; \n "
" std::unique_ptr<int[]> x(i); \n "
" } \n " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: i \n " , errout . str ( ) ) ;
2019-07-05 12:44:52 +02:00
check ( " void f() { \n "
" void* a = malloc(1); \n "
" void* b = freopen(f, p, a); \n "
" free(b); \n "
" } " ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.c:2] -> [test.c:3]: (error) Mismatching allocation and deallocation: a \n "
" [test.c:3] -> [test.c:4]: (error) Mismatching allocation and deallocation: b \n " , errout . str ( ) ) ;
2019-07-05 12:44:52 +02:00
check ( " void f() { \n "
" void* a; \n "
" void* b = realloc(a, 10); \n "
" free(b); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int * i = new int; \n "
" int * j = realloc(i, 2 * sizeof(int)); \n "
" delete[] j; \n "
" } " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: i \n "
" [test.cpp:3] -> [test.cpp:4]: (error) Mismatching allocation and deallocation: j \n " , errout . str ( ) ) ;
2022-11-18 19:45:25 +01:00
check ( " static void deleter(int* p) { free(p); } \n " // #11392
" void f() { \n "
" if (int* p = static_cast<int*>(malloc(4))) { \n "
" std::unique_ptr<int, decltype(&deleter)> guard(p, &deleter); \n "
" } \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" if (int* p = static_cast<int*>(malloc(4))) { \n "
" std::unique_ptr<int, decltype(&deleter)> guard(p, &deleter); \n "
" } \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
}
void smartPointerDeleter ( ) {
check ( " void f() { \n "
" FILE*f=fopen(fname,a); \n "
" std::unique_ptr<FILE> fp{f}; \n "
" } " , true ) ;
2019-09-22 21:50:02 +02:00
ASSERT_EQUALS ( " [test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f \n " , errout . str ( ) ) ;
2018-04-16 11:11:13 +02:00
check ( " void f() { \n "
" FILE*f=fopen(fname,a); \n "
" std::unique_ptr<FILE, decltype(&fclose)> fp{f, &fclose}; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" FILE*f=fopen(fname,a); \n "
" std::shared_ptr<FILE> fp{f, &fclose}; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct deleter { void operator()(FILE* f) { fclose(f); }}; \n "
" void f() { \n "
" FILE*f=fopen(fname,a); \n "
" std::unique_ptr<FILE, deleter> fp{f}; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int * create(); \n "
" void destroy(int * x); \n "
" void f() { \n "
" int x * = create() \n "
" std::unique_ptr<int, decltype(&destroy)> xp{x, &destroy()}; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " int * create(); \n "
" void destroy(int * x); \n "
" void f() { \n "
" int x * = create() \n "
" std::unique_ptr<int, decltype(&destroy)> xp(x, &destroy()); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-05-21 08:22:18 +02:00
check ( " void f() { \n "
" FILE*f=fopen(fname,a); \n "
" std::shared_ptr<FILE> fp{f, [](FILE* x) { fclose(x); }}; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" FILE*f=fopen(fname,a); \n "
" std::shared_ptr<FILE> fp{f, +[](FILE* x) { fclose(x); }}; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" FILE*f=fopen(fname,a); \n "
" std::shared_ptr<FILE> fp{f, [](FILE* x) { free(f); }}; \n "
" } " , true ) ;
2022-01-15 07:56:56 +01:00
TODO_ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f \n " , " " , errout . str ( ) ) ;
2018-05-21 08:22:18 +02:00
check ( " void f() { \n "
" FILE*f=fopen(fname,a); \n "
" std::shared_ptr<FILE> fp{f, [](FILE* x) {}}; \n "
" } " , true ) ;
2022-01-15 07:56:56 +01:00
TODO_ASSERT_EQUALS (
" [test.cpp:2] -> [test.cpp:3]: (error) Mismatching allocation and deallocation: f \n " , " " , errout . str ( ) ) ;
2018-05-21 08:22:18 +02:00
check ( " class C; \n "
" void f() { \n "
" C* c = new C{}; \n "
" std::shared_ptr<C> a{c, [](C*) {}}; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " class C; \n "
" void f() { \n "
" C* c = new C{}; \n "
" std::shared_ptr<C> a{c, [](C* x) { delete x; }}; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2018-05-05 18:06:49 +02:00
void smartPointerRelease ( ) {
check ( " void f() { \n "
" int * i = new int; \n "
" std::unique_ptr<int> x(i); \n "
" x.release(); \n "
" delete i; \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n "
" int * i = new int; \n "
" std::unique_ptr<int> x(i); \n "
" x.release(); \n "
" } \n " , true ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Memory leak: i \n " , errout . str ( ) ) ;
}
2012-05-26 08:53:46 +02:00
2014-11-20 14:20:09 +01:00
void return1 ( ) {
2012-05-26 08:53:46 +02:00
check ( " int f() { \n "
" char *p = malloc(100); \n "
" return 123; \n "
" } " ) ;
2012-06-30 16:23:10 +02:00
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void return2 ( ) {
2012-05-26 08:53:46 +02:00
check ( " char *f() { \n "
" char *p = malloc(100); \n "
" return p; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void return3 ( ) {
2012-05-26 08:53:46 +02:00
check ( " struct dev * f() { \n "
" struct ABC *abc = malloc(100); \n "
" return &abc->dev; \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void return4 ( ) { // ticket #3862
2012-06-04 21:32:11 +02:00
// avoid false positives
2012-06-01 19:08:50 +02:00
check ( " void f(char *p, int x) { \n "
2012-12-26 12:50:59 +01:00
" if (x==12) { \n "
2012-06-01 19:08:50 +02:00
" free(p); \n "
" throw 1; \n "
" } \n "
" free(p); \n "
2015-06-28 16:49:16 +02:00
" } " , true ) ;
2012-06-01 19:08:50 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-06-04 21:32:11 +02:00
check ( " void f(char *p, int x) { \n "
2012-12-26 12:50:59 +01:00
" if (x==12) { \n "
2012-06-04 21:32:11 +02:00
" delete p; \n "
" throw 1; \n "
" } \n "
" delete p; \n "
2015-06-28 16:49:16 +02:00
" } " , true ) ;
2012-06-04 21:32:11 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f(char *p, int x) { \n "
2012-12-26 12:50:59 +01:00
" if (x==12) { \n "
2012-06-04 21:32:11 +02:00
" delete [] p; \n "
" throw 1; \n "
" } \n "
" delete [] p; \n "
2015-06-28 16:49:16 +02:00
" } " , true ) ;
2012-06-04 21:32:11 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-06-01 19:08:50 +02:00
}
2016-05-15 20:27:44 +02:00
void return5 ( ) { // ticket #6397 - conditional allocation/deallocation and conditional return
// avoid false positives
check ( " void f(int *p, int x) { \n "
" if (x != 0) { \n "
" free(p); \n "
" } \n "
" if (x != 0) { \n "
" return; \n "
" } \n "
" *p = 0; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-07-26 07:03:58 +02:00
void return6 ( ) { // #8282
check ( " std::pair<char*, char*> f(size_t n) { \n "
" char* p = (char* )malloc(n); \n "
" return {p, p}; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2019-09-20 15:09:27 +02:00
void return7 ( ) { // #9343
check ( " uint8_t *f() { \n "
" void *x = malloc(1); \n "
" return (uint8_t *)x; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " uint8_t f() { \n "
" void *x = malloc(1); \n "
" return (uint8_t)x; \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: x \n " , errout . str ( ) ) ;
check ( " void** f() { \n "
" void *x = malloc(1); \n "
" return (void**)x; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void* f() { \n "
" void *x = malloc(1); \n "
" return (long long)x; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void* f() { \n "
" void *x = malloc(1); \n "
" return (void*)(short)x; \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: x \n " , errout . str ( ) ) ;
2019-09-21 14:59:54 +02:00
check ( " void* f() { \n "
" void *x = malloc(1); \n "
" return (mytype)x; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void* f() { \n " // Do not crash
" void *x = malloc(1); \n "
" return (mytype)y; \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: x \n " , errout . str ( ) ) ;
2019-09-20 15:09:27 +02:00
}
2019-09-22 19:18:31 +02:00
void return8 ( ) {
check ( " void* f() { \n "
" void *x = malloc(1); \n "
" return (x); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void* f() { \n "
" void *x = malloc(1); \n "
" return ((x)); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void* f() { \n "
" void *x = malloc(1); \n "
" return ((((x)))); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " char* f() { \n "
" void *x = malloc(1); \n "
" return (char*)(x); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2022-03-10 08:29:05 +01:00
void return9 ( ) {
check ( " void* f() { \n "
" void *x = malloc (sizeof (struct alloc)); \n "
" return x + sizeof (struct alloc); \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void test1 ( ) { // 3809
2012-06-01 19:01:19 +02:00
check ( " void f(double*&p) { \n "
" p = malloc(0x100); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void test2 ( ) { // 3899
2012-06-20 17:09:41 +02:00
check ( " struct Fred { \n "
" char *p; \n "
" void f1() { free(p); } \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void test3 ( ) { // 3954 - reference pointer
2012-07-17 16:28:34 +02:00
check ( " void f() { \n "
" char *&p = x(); \n "
" p = malloc(10); \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void test4 ( ) { // 5923 - static pointer
2014-06-23 16:05:28 +02:00
check ( " void f() { \n "
" static char *p; \n "
" if (!p) p = malloc(10); \n "
" if (x) { free(p); p = 0; } \n "
" }; " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void test5 ( ) { // unknown type
2015-01-28 13:45:40 +01:00
check ( " void f() { Fred *p = malloc(10); } " , true ) ;
2015-08-11 12:41:42 +02:00
ASSERT_EQUALS ( " [test.cpp:1]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2014-10-14 16:40:30 +02:00
2015-01-28 13:45:40 +01:00
check ( " void f() { Fred *p = malloc(10); } " , false ) ;
2014-10-14 16:40:30 +02:00
ASSERT_EQUALS ( " [test.c:1]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2015-08-11 12:41:42 +02:00
check ( " void f() { Fred *p = new Fred; } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2017-07-08 22:28:31 +02:00
check ( " void f() { Fred fred = malloc(10); } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-10-14 16:40:30 +02:00
}
2014-11-20 14:20:09 +01:00
void throw1 ( ) { // 3987 - Execution reach a 'throw'
2012-09-22 10:37:27 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" throw 123; \n "
2015-06-28 16:49:16 +02:00
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
2012-09-22 10:37:27 +02:00
check ( " void f() { \n "
" char *p; \n "
" try { \n "
" p = malloc(10); \n "
" throw 123; \n "
" } catch (...) { } \n "
" free(p); \n "
2015-06-28 16:49:16 +02:00
" } " , true ) ;
2012-09-22 10:37:27 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2016-05-13 14:53:32 +02:00
void throw2 ( ) { // do not miss ::NS::Except()
check ( " namespace NS { \n "
" class Except { \n "
" }; \n "
" } \n "
" void foo(int i) \n "
" { \n "
" int *pi = new int; \n "
" if (i == 42) { \n "
" delete pi; \n "
" throw ::NS::Except(); \n "
" } \n "
" delete pi; \n "
" } " , true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void configuration1 ( ) {
2012-05-26 08:53:46 +02:00
// Possible leak => configuration is required for complete analysis
// The user should be able to "white list" and "black list" functions.
// possible leak. If the function 'x' deallocates the pointer or
// takes the address, there is no leak.
check ( " void f() { \n "
" char *p = malloc(10); \n "
" x(p); \n "
" } " ) ;
2013-07-16 18:50:25 +02:00
ASSERT_EQUALS ( " [test.c:3]: (information) --check-library: Function x() should have <noreturn> configuration \n "
2015-02-03 18:35:52 +01:00
" [test.c:4]: (information) --check-library: Function x() should have <use>/<leak-ignore> configuration \n " ,
2013-07-16 18:50:25 +02:00
errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void configuration2 ( ) {
2012-05-26 08:53:46 +02:00
// possible leak. If the function 'x' deallocates the pointer or
// takes the address, there is no leak.
check ( " void f() { \n "
" char *p = malloc(10); \n "
" x(&p); \n "
" } " ) ;
2013-07-16 18:50:25 +02:00
ASSERT_EQUALS ( " [test.c:3]: (information) --check-library: Function x() should have <noreturn> configuration \n "
2015-02-03 18:35:52 +01:00
" [test.c:4]: (information) --check-library: Function x() should have <use>/<leak-ignore> configuration \n " ,
2013-07-16 18:50:25 +02:00
errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void configuration3 ( ) {
2019-07-18 15:23:19 +02:00
const char * code = " void f() { \n "
" char *p = malloc(10); \n "
" if (set_data(p)) { } \n "
" } " ;
check ( code ) ;
2015-02-03 18:35:52 +01:00
ASSERT_EQUALS ( " [test.c:4]: (information) --check-library: Function set_data() should have <use>/<leak-ignore> configuration \n " , errout . str ( ) ) ;
2019-07-18 15:23:19 +02:00
check ( code , true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (information) --check-library: Function set_data() should have <use>/<leak-ignore> configuration \n " , errout . str ( ) ) ;
code = " void f() { \n "
" char *p = malloc(10); \n "
" if (set_data(p)) { return; } \n "
" } " ;
check ( code ) ;
2015-02-03 18:35:52 +01:00
ASSERT_EQUALS ( " [test.c:3]: (information) --check-library: Function set_data() should have <use>/<leak-ignore> configuration \n "
" [test.c:4]: (information) --check-library: Function set_data() should have <use>/<leak-ignore> configuration \n "
2012-05-26 08:53:46 +02:00
, errout . str ( ) ) ;
2019-07-18 15:23:19 +02:00
check ( code , true ) ;
ASSERT_EQUALS ( " [test.cpp:3]: (information) --check-library: Function set_data() should have <use>/<leak-ignore> configuration \n "
" [test.cpp:4]: (information) --check-library: Function set_data() should have <use>/<leak-ignore> configuration \n "
, errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2014-11-20 14:20:09 +01:00
void configuration4 ( ) {
2012-05-26 08:53:46 +02:00
check ( " void f() { \n "
" char *p = malloc(10); \n "
" int ret = set_data(p); \n "
" return ret; \n "
" } " ) ;
2015-02-03 18:35:52 +01:00
ASSERT_EQUALS ( " [test.c:4]: (information) --check-library: Function set_data() should have <use>/<leak-ignore> configuration \n " , errout . str ( ) ) ;
2012-05-26 08:53:46 +02:00
}
2012-08-26 11:39:17 +02:00
2022-07-19 20:41:18 +02:00
void configuration5 ( ) {
check ( " void f() { \n "
" int(i); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-07-28 22:47:15 +02:00
check ( " void f() { \n "
" static_assert(1 == sizeof(char), \" test \" ); \n "
" } \n " , /*cpp*/ true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-08-03 19:04:10 +02:00
check ( " namespace pal { \n " // #11237
" struct AutoTimer {}; \n "
" } \n "
" int main() { \n "
" pal::AutoTimer(); \n "
" } \n " , /*cpp*/ true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct AutoTimer {}; \n "
" int main() { \n "
" AutoTimer(); \n "
" } \n " , /*cpp*/ true ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-08-04 21:35:18 +02:00
check ( " void f() { \n " // #8666
" asm( \" assembler code \" ); \n "
" asm volatile( \" assembler code \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { \n " // #11239
" asm goto( \" assembler code \" ); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2022-09-02 07:51:10 +02:00
check ( " void f() { \n "
" FILE* p = fopen( \" abc.txt \" , \" r \" ); \n "
" if (fclose(p) != 0) {} \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " struct S; \n "
" void f(int a, int b, S*& p) { \n "
" if (a == -1) { \n "
" FILE* file = fopen( \" abc.txt \" , \" r \" ); \n "
" } \n "
" if (b) { \n "
" void* buf = malloc(10); \n "
" p = reinterpret_cast<S*>(buf); \n "
" } \n "
" } \n " , /*cpp*/ true ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (error) Resource leak: file \n " , errout . str ( ) ) ;
2022-07-19 20:41:18 +02:00
}
2023-01-26 22:29:49 +01:00
void configuration6 ( ) { // #11198
check ( " void f() {} \n "
" void g() { \n "
" f(); \n "
" } \n " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void ptrptr ( ) {
2012-08-26 11:39:17 +02:00
check ( " void f() { \n "
" char **p = malloc(10); \n "
" } " ) ;
ASSERT_EQUALS ( " [test.c:3]: (error) Memory leak: p \n " , errout . str ( ) ) ;
}
2014-09-30 13:02:02 +02:00
2014-11-20 14:20:09 +01:00
void nestedAllocation ( ) {
2014-09-30 13:02:02 +02:00
check ( " void QueueDSMCCPacket(unsigned char *data, int length) { \n "
" unsigned char *dataCopy = malloc(length * sizeof(unsigned char)); \n "
" m_dsmccQueue.enqueue(new DSMCCPacket(dataCopy)); \n "
2015-06-14 15:49:49 +02:00
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (information) --check-library: Function DSMCCPacket() should have <use>/<leak-ignore> configuration \n " , errout . str ( ) ) ;
2014-09-30 13:02:02 +02:00
check ( " void QueueDSMCCPacket(unsigned char *data, int length) { \n "
" unsigned char *dataCopy = malloc(length * sizeof(unsigned char)); \n "
" m_dsmccQueue.enqueue(new DSMCCPacket(somethingunrelated)); \n "
2015-06-14 15:49:49 +02:00
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: dataCopy \n " , errout . str ( ) ) ;
2016-05-21 14:03:28 +02:00
check ( " void f() { \n "
" char *buf = new char[1000]; \n "
" clist.push_back(new (std::nothrow) C(buf)); \n "
" } " , true ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (information) --check-library: Function C() should have <use>/<leak-ignore> configuration \n " , errout . str ( ) ) ;
2015-06-14 15:49:49 +02:00
}
void testKeywords ( ) {
check ( " int main(int argc, char **argv) { \n "
" double *new = malloc(1*sizeof(double)); \n "
" free(new); \n "
" return 0; \n "
2015-06-28 16:49:16 +02:00
" } " , false ) ;
2015-06-14 15:49:49 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2014-09-30 13:02:02 +02:00
}
2016-05-26 17:42:27 +02:00
void inlineFunction ( ) {
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 ( ) ) ;
}
2018-05-14 13:08:33 +02:00
2018-05-14 22:48:37 +02:00
// #8262
void smartPtrInContainer ( ) {
check ( " std::list< std::shared_ptr<int> > mList; \n "
" void test(){ \n "
" int *pt = new int(1); \n "
" mList.push_back(std::shared_ptr<int>(pt)); \n "
" } \n " ,
true
2021-08-07 20:51:18 +02:00
) ;
2018-05-22 09:08:23 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2018-05-14 22:48:37 +02:00
}
2018-05-14 13:08:33 +02:00
2020-07-07 23:46:24 +02:00
void functionCallCastConfig ( ) { // #9652
Settings settingsFunctionCall = settings ;
const char xmldata [ ] = " <?xml version= \" 1.0 \" ?> \n "
" <def format= \" 2 \" > \n "
" <function name= \" free_func \" > \n "
" <noreturn>false</noreturn> \n "
" <arg nr= \" 1 \" > \n "
" <not-uninit/> \n "
" </arg> \n "
" <arg nr= \" 2 \" > \n "
" <not-uninit/> \n "
" </arg> \n "
" </function> \n "
" </def> " ;
tinyxml2 : : XMLDocument doc ;
doc . Parse ( xmldata , sizeof ( xmldata ) ) ;
settingsFunctionCall . library . load ( doc ) ;
check ( " void test_func() \n "
" { \n "
" char * buf = malloc(4); \n "
" free_func((void *)(1), buf); \n "
" } " , settingsFunctionCall ) ;
ASSERT_EQUALS ( " [test.cpp:5]: (information) --check-library: Function free_func() should have <use>/<leak-ignore> configuration \n " , errout . str ( ) ) ;
}
2022-04-28 19:50:16 +02:00
void functionCallLeakIgnoreConfig ( ) { // #7923
Settings settingsLeakIgnore = settings ;
const char xmldata [ ] = " <?xml version= \" 1.0 \" ?> \n "
" <def format= \" 2 \" > \n "
" <function name= \" SomeClass::someMethod \" > \n "
" <leak-ignore/> \n "
" <noreturn>false</noreturn> \n "
" <arg nr= \" 1 \" direction= \" in \" /> \n "
" </function> \n "
" </def> \n " ;
tinyxml2 : : XMLDocument doc ;
doc . Parse ( xmldata , sizeof ( xmldata ) ) ;
settingsLeakIgnore . library . load ( doc ) ;
check ( " void f() { \n "
" double* a = new double[1024]; \n "
" SomeClass::someMethod(a); \n "
" } \n " , settingsLeakIgnore ) ;
ASSERT_EQUALS ( " [test.cpp:4]: (error) Memory leak: a \n " , errout . str ( ) ) ;
}
2012-05-26 08:53:46 +02:00
} ;
REGISTER_TEST ( TestLeakAutoVar )
2015-05-19 20:16:00 +02:00
2020-12-31 09:34:53 +01:00
class TestLeakAutoVarRecursiveCountLimit : public TestFixture {
public :
2021-08-07 20:51:18 +02:00
TestLeakAutoVarRecursiveCountLimit ( ) : TestFixture ( " TestLeakAutoVarRecursiveCountLimit " ) { }
2020-12-31 09:34:53 +01:00
private :
Settings settings ;
void checkP ( const char code [ ] , bool cpp = false ) {
// Clear the error buffer..
errout . str ( " " ) ;
// Raw tokens..
std : : vector < std : : string > files ( 1 , cpp ? " test.cpp " : " test.c " ) ;
std : : istringstream istr ( code ) ;
const simplecpp : : TokenList tokens1 ( istr , files , files [ 0 ] ) ;
// Preprocess..
simplecpp : : TokenList tokens2 ( files ) ;
std : : map < std : : string , simplecpp : : TokenList * > filedata ;
simplecpp : : preprocess ( tokens2 , tokens1 , files , filedata , simplecpp : : DUI ( ) ) ;
// Tokenizer..
Tokenizer tokenizer ( & settings , this ) ;
tokenizer . createTokens ( std : : move ( tokens2 ) ) ;
tokenizer . simplifyTokens1 ( " " ) ;
settings . checkLibrary = true ;
2023-01-29 17:23:03 +01:00
// Check for leaks..
runChecks < CheckLeakAutoVar > ( & tokenizer , & settings , this ) ;
2020-12-31 09:34:53 +01:00
}
2022-02-10 23:02:24 +01:00
void run ( ) override {
2020-12-31 09:34:53 +01:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
TEST_CASE ( recursiveCountLimit ) ; // #5872 #6157 #9097
}
void recursiveCountLimit ( ) { // #5872 #6157 #9097
ASSERT_THROW ( checkP ( " #define ONE else if (0) { } \n "
" #define TEN ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE \n "
" #define HUN TEN TEN TEN TEN TEN TEN TEN TEN TEN TEN \n "
" #define THOU HUN HUN HUN HUN HUN HUN HUN HUN HUN HUN \n "
" void foo() { \n "
" if (0) { } \n "
" THOU THOU \n "
" } " ) , InternalError ) ;
ASSERT_NO_THROW ( checkP ( " #define ONE if (0) { } \n "
" #define TEN ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE \n "
" #define HUN TEN TEN TEN TEN TEN TEN TEN TEN TEN TEN \n "
" #define THOU HUN HUN HUN HUN HUN HUN HUN HUN HUN HUN \n "
" void foo() { \n "
" if (0) { } \n "
" THOU THOU \n "
" } " ) ) ;
}
} ;
REGISTER_TEST ( TestLeakAutoVarRecursiveCountLimit )
2015-05-19 20:16:00 +02:00
2021-08-07 20:51:18 +02:00
class TestLeakAutoVarStrcpy : public TestFixture {
2020-01-09 08:47:36 +01:00
public :
2021-08-07 20:51:18 +02:00
TestLeakAutoVarStrcpy ( ) : TestFixture ( " TestLeakAutoVarStrcpy " ) { }
2020-01-09 08:47:36 +01:00
private :
Settings settings ;
2021-11-29 07:34:39 +01:00
void check_ ( const char * file , int line , const char code [ ] ) {
2020-01-09 08:47:36 +01:00
// Clear the error buffer..
errout . str ( " " ) ;
// 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 ) ;
2020-01-09 08:47:36 +01:00
settings . checkLibrary = true ;
2023-01-29 17:23:03 +01:00
// Check for leaks..
runChecks < CheckLeakAutoVar > ( & tokenizer , & settings , this ) ;
2020-01-09 08:47:36 +01:00
}
2022-02-10 23:02:24 +01:00
void run ( ) override {
2020-01-09 08:47:36 +01:00
LOAD_LIB_2 ( settings . library , " std.cfg " ) ;
TEST_CASE ( returnedValue ) ; // #9298
2020-02-17 10:25:30 +01:00
TEST_CASE ( fclose_false_positive ) ; // #9575
2020-01-09 08:47:36 +01:00
}
void returnedValue ( ) { // #9298
check ( " char *m; \n "
" void strcpy_returnedvalue(const char* str) \n "
" { \n "
" char* ptr = new char[strlen(str)+1]; \n "
" m = strcpy(ptr, str); \n "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-02-17 10:25:30 +01:00
void fclose_false_positive ( ) { // #9575
check ( " int f(FILE *fp) { return fclose(fp); } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2020-01-09 08:47:36 +01:00
} ;
2015-05-19 20:16:00 +02:00
2020-01-09 08:47:36 +01:00
REGISTER_TEST ( TestLeakAutoVarStrcpy )
2015-05-19 20:16:00 +02:00
class TestLeakAutoVarWindows : public TestFixture {
public :
2021-08-07 20:51:18 +02:00
TestLeakAutoVarWindows ( ) : TestFixture ( " TestLeakAutoVarWindows " ) { }
2015-05-19 20:16:00 +02:00
private :
Settings settings ;
2021-11-29 07:34:39 +01:00
void check_ ( const char * file , int line , const char code [ ] ) {
2015-05-19 20:16:00 +02:00
// Clear the error buffer..
errout . str ( " " ) ;
// Tokenize..
Tokenizer tokenizer ( & settings , this ) ;
std : : istringstream istr ( code ) ;
2021-11-29 07:34:39 +01:00
ASSERT_LOC ( tokenizer . tokenize ( istr , " test.c " ) , file , line ) ;
2015-05-19 20:16:00 +02:00
// Check for leaks..
2023-01-29 17:23:03 +01:00
runChecks < CheckLeakAutoVar > ( & tokenizer , & settings , this ) ;
2015-05-19 20:16:00 +02:00
}
2022-02-10 23:02:24 +01:00
void run ( ) override {
2015-05-19 20:16:00 +02:00
LOAD_LIB_2 ( settings . library , " windows.cfg " ) ;
TEST_CASE ( heapDoubleFree ) ;
}
void heapDoubleFree ( ) {
check ( " void f() { "
" HANDLE MyHeap = HeapCreate(0, 0, 0); "
" int *a = HeapAlloc(MyHeap, 0, sizeof(int)); "
" int *b = HeapAlloc(MyHeap, 0, sizeof(int)); "
" HeapFree(MyHeap, 0, a); "
" HeapFree(MyHeap, 0, b); "
" HeapDestroy(MyHeap); "
" } " ) ;
2016-05-22 17:18:50 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2015-05-19 20:16:00 +02:00
check ( " void f() { "
" int *a = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); "
" int *b = HeapAlloc(GetProcessHeap(), 0, sizeof(int)); "
" HeapFree(GetProcessHeap(), 0, a); "
" HeapFree(GetProcessHeap(), 0, b); "
" } " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
check ( " void f() { "
" HANDLE MyHeap = HeapCreate(0, 0, 0); "
" int *a = HeapAlloc(MyHeap, 0, sizeof(int)); "
" int *b = HeapAlloc(MyHeap, 0, sizeof(int)); "
" HeapFree(MyHeap, 0, a); "
" HeapDestroy(MyHeap); "
" } " ) ;
2016-05-22 17:18:50 +02:00
ASSERT_EQUALS ( " [test.c:1]: (error) Memory leak: b \n " , errout . str ( ) ) ;
2015-05-19 20:16:00 +02:00
check ( " void f() { "
" HANDLE MyHeap = HeapCreate(0, 0, 0); "
" int *a = HeapAlloc(MyHeap, 0, sizeof(int)); "
" int *b = HeapAlloc(MyHeap, 0, sizeof(int)); "
" HeapFree(MyHeap, 0, a); "
" HeapFree(MyHeap, 0, b); "
" } " ) ;
2016-05-22 17:18:50 +02:00
TODO_ASSERT_EQUALS ( " [test.c:1] (error) Resource leak: MyHeap " ,
" " , errout . str ( ) ) ;
2015-05-19 20:16:00 +02:00
check ( " void f() { "
" HANDLE MyHeap = HeapCreate(0, 0, 0); "
" int *a = HeapAlloc(MyHeap, 0, sizeof(int)); "
" int *b = HeapAlloc(MyHeap, 0, sizeof(int)); "
" HeapFree(MyHeap, 0, a); "
" } " ) ;
2016-05-22 17:18:50 +02:00
TODO_ASSERT_EQUALS ( " [test.c:1] (error) Memory leak: MyHeap \n "
" [test.c:1] (error) Memory leak: b " ,
" [test.c:1]: (error) Memory leak: b \n " , errout . str ( ) ) ;
2015-05-19 20:16:00 +02:00
}
} ;
2015-10-07 14:30:01 +02:00
REGISTER_TEST ( TestLeakAutoVarWindows )