2012-12-02 13:20:44 +00:00
// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s
# include "Inputs/system-header-simulator.h"
2012-04-14 14:01:31 +00:00
2012-08-15 20:02:54 +00:00
void clang_analyzer_eval ( int ) ;
2009-11-18 14:59:57 +00:00
typedef __typeof ( sizeof ( int ) ) size_t ;
void * malloc ( size_t ) ;
2012-04-14 14:01:31 +00:00
void * valloc ( size_t ) ;
2009-11-18 14:59:57 +00:00
void free ( void * ) ;
2009-12-15 18:49:47 +00:00
void * realloc ( void * ptr , size_t size ) ;
2012-04-14 14:01:31 +00:00
void * reallocf ( void * ptr , size_t size ) ;
2009-12-15 18:49:47 +00:00
void * calloc ( size_t nmemb , size_t size ) ;
2012-08-15 20:02:54 +00:00
char * strdup ( const char * s ) ;
char * strndup ( const char * s , size_t n ) ;
2013-04-08 18:45:10 +00:00
int memcmp ( const void * s1 , const void * s2 , size_t n ) ;
2012-04-14 14:01:31 +00:00
void myfoo ( int * p ) ;
void myfooint ( int p ) ;
char * fooRetPtr ( ) ;
2009-11-18 14:59:57 +00:00
void f1 ( ) {
2010-05-27 15:17:06 +00:00
int * p = malloc ( 12 ) ;
2013-06-10 20:45:12 +00:00
return ; // expected-warning{{Potential leak of memory pointed to by 'p'}}
2009-11-18 14:59:57 +00:00
}
void f2 ( ) {
2010-05-27 15:17:06 +00:00
int * p = malloc ( 12 ) ;
2009-11-18 14:59:57 +00:00
free ( p ) ;
2012-04-14 14:01:31 +00:00
free ( p ) ; // expected-warning{{Attempt to free released memory}}
2009-11-18 14:59:57 +00:00
}
2011-05-02 19:39:53 +00:00
void f2_realloc_0 ( ) {
int * p = malloc ( 12 ) ;
realloc ( p , 0 ) ;
2012-04-14 14:01:31 +00:00
realloc ( p , 0 ) ; // expected-warning{{Attempt to free released memory}}
2011-05-02 19:39:53 +00:00
}
void f2_realloc_1 ( ) {
int * p = malloc ( 12 ) ;
2011-10-20 21:14:49 +00:00
int * q = realloc ( p , 0 ) ; // no-warning
2011-05-02 19:39:53 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocNotNullPtr ( unsigned sizeIn ) {
unsigned size = 12 ;
char * p = ( char * ) malloc ( size ) ;
if ( p ) {
char * q = ( char * ) realloc ( p , sizeIn ) ;
2013-06-10 20:45:12 +00:00
char x = * q ; // expected-warning {{Potential leak of memory pointed to by 'q'}}
2012-04-14 14:01:31 +00:00
}
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
int * realloctest1 ( ) {
int * q = malloc ( 12 ) ;
q = realloc ( q , 20 ) ;
return q ; // no warning - returning the allocated value
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
// p should be freed if realloc fails.
void reallocFails ( ) {
char * p = malloc ( 12 ) ;
char * r = realloc ( p , 12 + 1 ) ;
if ( ! r ) {
free ( p ) ;
} else {
free ( r ) ;
}
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocSizeZero1 ( ) {
char * p = malloc ( 12 ) ;
char * r = realloc ( p , 0 ) ;
if ( ! r ) {
2012-08-15 20:02:54 +00:00
free ( p ) ; // expected-warning {{Attempt to free released memory}}
2012-04-14 14:01:31 +00:00
} else {
free ( r ) ;
}
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocSizeZero2 ( ) {
char * p = malloc ( 12 ) ;
char * r = realloc ( p , 0 ) ;
if ( ! r ) {
2012-08-15 20:02:54 +00:00
free ( p ) ; // expected-warning {{Attempt to free released memory}}
2012-04-14 14:01:31 +00:00
} else {
free ( r ) ;
}
free ( p ) ; // expected-warning {{Attempt to free released memory}}
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocSizeZero3 ( ) {
char * p = malloc ( 12 ) ;
char * r = realloc ( p , 0 ) ;
free ( r ) ;
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocSizeZero4 ( ) {
char * r = realloc ( 0 , 0 ) ;
free ( r ) ;
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocSizeZero5 ( ) {
char * r = realloc ( 0 , 0 ) ;
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocPtrZero1 ( ) {
2013-04-08 18:45:10 +00:00
char * r = realloc ( 0 , 12 ) ;
2013-06-10 20:45:12 +00:00
} // expected-warning {{Potential leak of memory pointed to by 'r'}}
2010-09-17 15:54:40 +00:00
2012-04-14 14:01:31 +00:00
void reallocPtrZero2 ( ) {
char * r = realloc ( 0 , 12 ) ;
if ( r )
free ( r ) ;
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocPtrZero3 ( ) {
char * r = realloc ( 0 , 12 ) ;
free ( r ) ;
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocRadar6337483_1 ( ) {
char * buf = malloc ( 100 ) ;
buf = ( char * ) realloc ( buf , 0x1000000 ) ;
if ( ! buf ) {
2013-06-10 20:45:12 +00:00
return ; // expected-warning {{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
}
free ( buf ) ;
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocRadar6337483_2 ( ) {
char * buf = malloc ( 100 ) ;
char * buf2 = ( char * ) realloc ( buf , 0x1000000 ) ;
2013-04-08 18:45:10 +00:00
if ( ! buf2 ) {
2012-04-14 14:01:31 +00:00
;
} else {
free ( buf2 ) ;
}
2013-06-10 20:45:12 +00:00
} // expected-warning {{Potential leak of memory pointed to by}}
2010-09-17 15:54:40 +00:00
2012-04-14 14:01:31 +00:00
void reallocRadar6337483_3 ( ) {
char * buf = malloc ( 100 ) ;
char * tmp ;
tmp = ( char * ) realloc ( buf , 0x1000000 ) ;
if ( ! tmp ) {
free ( buf ) ;
return ;
}
buf = tmp ;
free ( buf ) ;
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocRadar6337483_4 ( ) {
char * buf = malloc ( 100 ) ;
char * buf2 = ( char * ) realloc ( buf , 0x1000000 ) ;
if ( ! buf2 ) {
2013-06-10 20:45:12 +00:00
return ; // expected-warning {{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
} else {
free ( buf2 ) ;
}
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
int * reallocfTest1 ( ) {
int * q = malloc ( 12 ) ;
q = reallocf ( q , 20 ) ;
return q ; // no warning - returning the allocated value
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocfRadar6337483_4 ( ) {
char * buf = malloc ( 100 ) ;
char * buf2 = ( char * ) reallocf ( buf , 0x1000000 ) ;
if ( ! buf2 ) {
return ; // no warning - reallocf frees even on failure
} else {
free ( buf2 ) ;
}
2010-09-17 15:54:40 +00:00
}
2012-04-14 14:01:31 +00:00
void reallocfRadar6337483_3 ( ) {
char * buf = malloc ( 100 ) ;
char * tmp ;
tmp = ( char * ) reallocf ( buf , 0x1000000 ) ;
if ( ! tmp ) {
free ( buf ) ; // expected-warning {{Attempt to free released memory}}
return ;
}
buf = tmp ;
free ( buf ) ;
}
void reallocfPtrZero1 ( ) {
2013-04-08 18:45:10 +00:00
char * r = reallocf ( 0 , 12 ) ;
2013-06-10 20:45:12 +00:00
} // expected-warning {{Potential leak of memory pointed to by}}
2010-09-17 15:54:40 +00:00
2009-11-18 14:59:57 +00:00
// This case tests that storing malloc'ed memory to a static variable which is
// then returned is not leaked. In the absence of known contracts for functions
// or inter-procedural analysis, this is a conservative answer.
int * f3 ( ) {
static int * p = 0 ;
2010-05-27 15:17:06 +00:00
p = malloc ( 12 ) ;
2009-11-18 14:59:57 +00:00
return p ; // no-warning
}
// This case tests that storing malloc'ed memory to a static global variable
// which is then returned is not leaked. In the absence of known contracts for
// functions or inter-procedural analysis, this is a conservative answer.
static int * p_f4 = 0 ;
int * f4 ( ) {
2010-05-27 15:17:06 +00:00
p_f4 = malloc ( 12 ) ;
2009-11-18 14:59:57 +00:00
return p_f4 ; // no-warning
}
2009-12-15 18:49:47 +00:00
int * f5 ( ) {
2010-05-27 15:17:06 +00:00
int * q = malloc ( 12 ) ;
2009-12-15 18:49:47 +00:00
q = realloc ( q , 20 ) ;
return q ; // no-warning
}
2010-01-01 10:34:51 +00:00
void f6 ( ) {
2010-05-27 15:17:06 +00:00
int * p = malloc ( 12 ) ;
2010-01-01 10:34:51 +00:00
if ( ! p )
return ; // no-warning
else
free ( p ) ;
}
2010-01-23 11:10:26 +00:00
2011-05-02 19:39:53 +00:00
void f6_realloc ( ) {
int * p = malloc ( 12 ) ;
if ( ! p )
return ; // no-warning
else
realloc ( p , 0 ) ;
}
2010-01-23 11:10:26 +00:00
char * doit2 ( ) ;
void pr6069 ( ) {
char * buf = doit2 ( ) ;
free ( buf ) ;
}
2010-02-16 09:31:36 +00:00
void pr6293 ( ) {
free ( 0 ) ;
}
2010-03-10 17:45:58 +00:00
void f7 ( ) {
char * x = ( char * ) malloc ( 4 ) ;
free ( x ) ;
2012-04-14 14:01:31 +00:00
x [ 0 ] = ' a ' ; // expected-warning{{Use of memory after it is freed}}
2010-03-10 17:45:58 +00:00
}
2010-05-27 15:17:06 +00:00
2012-08-15 20:02:54 +00:00
void f8 ( ) {
char * x = ( char * ) malloc ( 4 ) ;
free ( x ) ;
char * y = strndup ( x , 4 ) ; // expected-warning{{Use of memory after it is freed}}
}
2011-05-02 19:39:53 +00:00
void f7_realloc ( ) {
char * x = ( char * ) malloc ( 4 ) ;
realloc ( x , 0 ) ;
2012-04-14 14:01:31 +00:00
x [ 0 ] = ' a ' ; // expected-warning{{Use of memory after it is freed}}
2011-05-02 19:39:53 +00:00
}
2010-05-27 15:17:06 +00:00
void PR6123 ( ) {
2012-08-19 10:33:04 +00:00
int * x = malloc ( 11 ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
2010-05-27 15:17:06 +00:00
}
void PR7217 ( ) {
2012-08-19 10:33:04 +00:00
int * buf = malloc ( 2 ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
2010-05-27 15:17:06 +00:00
buf [ 1 ] = ' c ' ; // not crash
2010-07-13 17:21:42 +00:00
}
2014-11-24 09:15:30 +00:00
void cast_emtpy_struct ( ) {
struct st {
} ;
struct st * s = malloc ( sizeof ( struct st ) ) ; // no-warning
free ( s ) ;
}
void cast_struct_1 ( ) {
struct st {
int i [ 100 ] ;
char j [ ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) ) ; // no-warning
free ( s ) ;
}
void cast_struct_2 ( ) {
struct st {
int i [ 100 ] ;
char j [ 0 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) ) ; // no-warning
free ( s ) ;
}
void cast_struct_3 ( ) {
struct st {
int i [ 100 ] ;
char j [ 1 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) ) ; // no-warning
free ( s ) ;
}
void cast_struct_4 ( ) {
struct st {
int i [ 100 ] ;
char j [ 2 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) ) ; // no-warning
free ( s ) ;
}
void cast_struct_5 ( ) {
struct st {
char i [ 200 ] ;
char j [ 1 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) - sizeof ( char ) ) ; // no-warning
free ( s ) ;
}
void cast_struct_warn_1 ( ) {
struct st {
int i [ 100 ] ;
char j [ 2 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 2 ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
free ( s ) ;
}
void cast_struct_warn_2 ( ) {
struct st {
int i [ 100 ] ;
char j [ 2 ] ;
} ;
struct st * s = malloc ( 2 ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
free ( s ) ;
}
void cast_struct_flex_array_1 ( ) {
struct st {
int i [ 100 ] ;
char j [ ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 3 ) ; // no-warning
free ( s ) ;
}
void cast_struct_flex_array_2 ( ) {
struct st {
int i [ 100 ] ;
char j [ 0 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 3 ) ; // no-warning
free ( s ) ;
}
void cast_struct_flex_array_3 ( ) {
struct st {
int i [ 100 ] ;
char j [ 1 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 3 ) ; // no-warning
free ( s ) ;
}
void cast_struct_flex_array_4 ( ) {
struct foo {
char f [ 32 ] ;
} ;
struct st {
char i [ 100 ] ;
struct foo data [ ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 3 * sizeof ( struct foo ) ) ; // no-warning
free ( s ) ;
}
void cast_struct_flex_array_5 ( ) {
struct foo {
char f [ 32 ] ;
} ;
struct st {
char i [ 100 ] ;
struct foo data [ 0 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 3 * sizeof ( struct foo ) ) ; // no-warning
free ( s ) ;
}
void cast_struct_flex_array_6 ( ) {
struct foo {
char f [ 32 ] ;
} ;
struct st {
char i [ 100 ] ;
struct foo data [ 1 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 3 * sizeof ( struct foo ) ) ; // no-warning
free ( s ) ;
}
void cast_struct_flex_array_warn_1 ( ) {
struct foo {
char f [ 32 ] ;
} ;
struct st {
char i [ 100 ] ;
struct foo data [ ] ;
} ;
struct st * s = malloc ( 3 * sizeof ( struct st ) + 3 * sizeof ( struct foo ) ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
free ( s ) ;
}
void cast_struct_flex_array_warn_2 ( ) {
struct foo {
char f [ 32 ] ;
} ;
struct st {
char i [ 100 ] ;
struct foo data [ 0 ] ;
} ;
struct st * s = malloc ( 3 * sizeof ( struct st ) + 3 * sizeof ( struct foo ) ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
free ( s ) ;
}
void cast_struct_flex_array_warn_3 ( ) {
struct foo {
char f [ 32 ] ;
} ;
struct st {
char i [ 100 ] ;
struct foo data [ 1 ] ;
} ;
struct st * s = malloc ( 3 * sizeof ( struct st ) + 3 * sizeof ( struct foo ) ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
free ( s ) ;
}
void cast_struct_flex_array_warn_4 ( ) {
struct st {
int i [ 100 ] ;
int j [ ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 3 ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
free ( s ) ;
}
void cast_struct_flex_array_warn_5 ( ) {
struct st {
int i [ 100 ] ;
int j [ 0 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 3 ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
free ( s ) ;
}
void cast_struct_flex_array_warn_6 ( ) {
struct st {
int i [ 100 ] ;
int j [ 1 ] ;
} ;
struct st * s = malloc ( sizeof ( struct st ) + 3 ) ; // expected-warning{{Cast a region whose size is not a multiple of the destination type size}}
free ( s ) ;
}
2010-07-13 17:21:42 +00:00
void mallocCastToVoid ( ) {
void * p = malloc ( 2 ) ;
const void * cp = p ; // not crash
free ( p ) ;
}
void mallocCastToFP ( ) {
void * p = malloc ( 2 ) ;
void ( * fp ) ( ) = p ; // not crash
free ( p ) ;
}
// This tests that malloc() buffers are undefined by default
char mallocGarbage ( ) {
char * buf = malloc ( 2 ) ;
char result = buf [ 1 ] ; // expected-warning{{undefined}}
free ( buf ) ;
return result ;
}
// This tests that calloc() buffers need to be freed
void callocNoFree ( ) {
char * buf = calloc ( 2 , 2 ) ;
2013-06-10 20:45:12 +00:00
return ; // expected-warning{{Potential leak of memory pointed to by 'buf'}}
2010-07-13 17:21:42 +00:00
}
// These test that calloc() buffers are zeroed by default
char callocZeroesGood ( ) {
char * buf = calloc ( 2 , 2 ) ;
char result = buf [ 3 ] ; // no-warning
if ( buf [ 1 ] = = 0 ) {
free ( buf ) ;
}
return result ; // no-warning
}
2010-05-27 15:17:06 +00:00
2010-07-13 17:21:42 +00:00
char callocZeroesBad ( ) {
char * buf = calloc ( 2 , 2 ) ;
char result = buf [ 3 ] ; // no-warning
if ( buf [ 1 ] ! = 0 ) {
2010-09-17 15:54:40 +00:00
free ( buf ) ; // expected-warning{{never executed}}
2010-07-13 17:21:42 +00:00
}
2013-06-10 20:45:12 +00:00
return result ; // expected-warning{{Potential leak of memory pointed to by 'buf'}}
2010-05-27 15:17:06 +00:00
}
2012-04-14 14:01:31 +00:00
void nullFree ( ) {
int * p = 0 ;
free ( p ) ; // no warning - a nop
}
void paramFree ( int * p ) {
myfoo ( p ) ;
free ( p ) ; // no warning
2012-08-15 20:02:54 +00:00
myfoo ( p ) ; // expected-warning {{Use of memory after it is freed}}
2012-04-14 14:01:31 +00:00
}
int * mallocEscapeRet ( ) {
int * p = malloc ( 12 ) ;
return p ; // no warning
}
void mallocEscapeFoo ( ) {
int * p = malloc ( 12 ) ;
myfoo ( p ) ;
return ; // no warning
}
void mallocEscapeFree ( ) {
int * p = malloc ( 12 ) ;
myfoo ( p ) ;
free ( p ) ;
}
void mallocEscapeFreeFree ( ) {
int * p = malloc ( 12 ) ;
myfoo ( p ) ;
free ( p ) ;
free ( p ) ; // expected-warning{{Attempt to free released memory}}
}
void mallocEscapeFreeUse ( ) {
int * p = malloc ( 12 ) ;
myfoo ( p ) ;
free ( p ) ;
myfoo ( p ) ; // expected-warning{{Use of memory after it is freed}}
}
int * myalloc ( ) ;
void myalloc2 ( int * * p ) ;
void mallocEscapeFreeCustomAlloc ( ) {
int * p = malloc ( 12 ) ;
myfoo ( p ) ;
free ( p ) ;
p = myalloc ( ) ;
free ( p ) ; // no warning
}
void mallocEscapeFreeCustomAlloc2 ( ) {
int * p = malloc ( 12 ) ;
myfoo ( p ) ;
free ( p ) ;
myalloc2 ( & p ) ;
free ( p ) ; // no warning
}
void mallocBindFreeUse ( ) {
int * x = malloc ( 12 ) ;
int * y = x ;
free ( y ) ;
myfoo ( x ) ; // expected-warning{{Use of memory after it is freed}}
}
void mallocEscapeMalloc ( ) {
int * p = malloc ( 12 ) ;
myfoo ( p ) ;
2013-04-08 18:45:10 +00:00
p = malloc ( 12 ) ;
2013-06-10 20:45:12 +00:00
} // expected-warning{{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
void mallocMalloc ( ) {
int * p = malloc ( 12 ) ;
2013-04-08 18:45:10 +00:00
p = malloc ( 12 ) ;
2013-06-10 20:45:12 +00:00
} // expected-warning {{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
void mallocFreeMalloc ( ) {
int * p = malloc ( 12 ) ;
free ( p ) ;
p = malloc ( 12 ) ;
free ( p ) ;
}
void mallocFreeUse_params ( ) {
int * p = malloc ( 12 ) ;
free ( p ) ;
myfoo ( p ) ; //expected-warning{{Use of memory after it is freed}}
}
void mallocFreeUse_params2 ( ) {
int * p = malloc ( 12 ) ;
free ( p ) ;
myfooint ( * p ) ; //expected-warning{{Use of memory after it is freed}}
}
void mallocFailedOrNot ( ) {
int * p = malloc ( 12 ) ;
if ( ! p )
free ( p ) ;
else
free ( p ) ;
}
struct StructWithInt {
int g ;
} ;
int * mallocReturnFreed ( ) {
int * p = malloc ( 12 ) ;
free ( p ) ;
return p ; // expected-warning {{Use of memory after it is freed}}
}
int useAfterFreeStruct ( ) {
struct StructWithInt * px = malloc ( sizeof ( struct StructWithInt ) ) ;
px - > g = 5 ;
free ( px ) ;
return px - > g ; // expected-warning {{Use of memory after it is freed}}
}
void nonSymbolAsFirstArg ( int * pp , struct StructWithInt * p ) ;
void mallocEscapeFooNonSymbolArg ( ) {
struct StructWithInt * p = malloc ( sizeof ( struct StructWithInt ) ) ;
nonSymbolAsFirstArg ( & p - > g , p ) ;
return ; // no warning
}
void mallocFailedOrNotLeak ( ) {
int * p = malloc ( 12 ) ;
if ( p = = 0 )
return ; // no warning
else
2013-06-10 20:45:12 +00:00
return ; // expected-warning {{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
}
void mallocAssignment ( ) {
char * p = malloc ( 12 ) ;
2013-04-08 18:45:10 +00:00
p = fooRetPtr ( ) ;
} // expected-warning {{leak}}
2012-04-14 14:01:31 +00:00
int vallocTest ( ) {
char * mem = valloc ( 12 ) ;
2013-06-10 20:45:12 +00:00
return 0 ; // expected-warning {{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
}
void vallocEscapeFreeUse ( ) {
int * p = valloc ( 12 ) ;
myfoo ( p ) ;
free ( p ) ;
myfoo ( p ) ; // expected-warning{{Use of memory after it is freed}}
}
int * Gl ;
struct GlStTy {
int * x ;
} ;
struct GlStTy GlS = { 0 } ;
void GlobalFree ( ) {
free ( Gl ) ;
}
void GlobalMalloc ( ) {
Gl = malloc ( 12 ) ;
}
void GlobalStructMalloc ( ) {
int * a = malloc ( 12 ) ;
GlS . x = a ;
}
void GlobalStructMallocFree ( ) {
int * a = malloc ( 12 ) ;
GlS . x = a ;
free ( GlS . x ) ;
}
char * ArrayG [ 12 ] ;
void globalArrayTest ( ) {
char * p = ( char * ) malloc ( 12 ) ;
ArrayG [ 0 ] = p ;
}
// Make sure that we properly handle a pointer stored into a local struct/array.
typedef struct _StructWithPtr {
int * memP ;
} StructWithPtr ;
static StructWithPtr arrOfStructs [ 10 ] ;
void testMalloc ( ) {
int * x = malloc ( 12 ) ;
StructWithPtr St ;
St . memP = x ;
2012-08-15 20:02:54 +00:00
arrOfStructs [ 0 ] = St ; // no-warning
2012-04-14 14:01:31 +00:00
}
StructWithPtr testMalloc2 ( ) {
int * x = malloc ( 12 ) ;
StructWithPtr St ;
St . memP = x ;
2012-08-15 20:02:54 +00:00
return St ; // no-warning
2012-04-14 14:01:31 +00:00
}
int * testMalloc3 ( ) {
int * x = malloc ( 12 ) ;
int * y = x ;
2012-08-15 20:02:54 +00:00
return y ; // no-warning
}
void testStructLeak ( ) {
StructWithPtr St ;
St . memP = malloc ( 12 ) ;
2013-06-10 20:45:12 +00:00
return ; // expected-warning {{Potential leak of memory pointed to by 'St.memP'}}
2012-04-14 14:01:31 +00:00
}
void testElemRegion1 ( ) {
char * x = ( void * ) malloc ( 2 ) ;
int * ix = ( int * ) x ;
free ( & ( x [ 0 ] ) ) ;
}
void testElemRegion2 ( int * * pp ) {
int * p = malloc ( 12 ) ;
* pp = p ;
free ( pp [ 0 ] ) ;
}
void testElemRegion3 ( int * * pp ) {
int * p = malloc ( 12 ) ;
* pp = p ;
free ( * pp ) ;
}
// Region escape testing.
unsigned takePtrToPtr ( int * * p ) ;
void PassTheAddrOfAllocatedData ( int f ) {
int * p = malloc ( 12 ) ;
// We don't know what happens after the call. Should stop tracking here.
if ( takePtrToPtr ( & p ) )
f + + ;
free ( p ) ; // no warning
}
struct X {
int * p ;
} ;
unsigned takePtrToStruct ( struct X * s ) ;
int * * foo2 ( int * g , int f ) {
int * p = malloc ( 12 ) ;
struct X * px = malloc ( sizeof ( struct X ) ) ;
px - > p = p ;
// We don't know what happens after this call. Should not track px nor p.
if ( takePtrToStruct ( px ) )
f + + ;
free ( p ) ;
return 0 ;
}
struct X * RegInvalidationDetect1 ( struct X * s2 ) {
struct X * px = malloc ( sizeof ( struct X ) ) ;
px - > p = 0 ;
px = s2 ;
2013-06-10 20:45:12 +00:00
return px ; // expected-warning {{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
}
struct X * RegInvalidationGiveUp1 ( ) {
int * p = malloc ( 12 ) ;
struct X * px = malloc ( sizeof ( struct X ) ) ;
px - > p = p ;
return px ;
}
int * * RegInvalidationDetect2 ( int * * pp ) {
int * p = malloc ( 12 ) ;
pp = & p ;
pp + + ;
2013-06-10 20:45:12 +00:00
return 0 ; // expected-warning {{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
}
extern void exit ( int ) __attribute__ ( ( __noreturn__ ) ) ;
void mallocExit ( int * g ) {
struct xx * p = malloc ( 12 ) ;
if ( g ! = 0 )
exit ( 1 ) ;
free ( p ) ;
return ;
}
extern void __assert_fail ( __const char * __assertion , __const char * __file ,
unsigned int __line , __const char * __function )
__attribute__ ( ( __noreturn__ ) ) ;
# define assert(expr) \
( ( expr ) ? ( void ) ( 0 ) : __assert_fail ( # expr , __FILE__ , __LINE__ , __func__ ) )
void mallocAssert ( int * g ) {
struct xx * p = malloc ( 12 ) ;
assert ( g ! = 0 ) ;
free ( p ) ;
return ;
}
void doNotInvalidateWhenPassedToSystemCalls ( char * s ) {
char * p = malloc ( 12 ) ;
strlen ( p ) ;
2013-04-08 18:45:10 +00:00
strcpy ( p , s ) ;
2013-12-22 00:07:40 +00:00
strcpy ( s , p ) ;
strcpy ( p , p ) ;
memcpy ( p , s , 1 ) ;
memcpy ( s , p , 1 ) ;
memcpy ( p , p , 1 ) ;
2013-04-08 18:45:10 +00:00
} // expected-warning {{leak}}
2012-04-14 14:01:31 +00:00
2013-12-22 00:07:40 +00:00
// Treat source buffer contents as escaped.
void escapeSourceContents ( char * s ) {
char * p = malloc ( 12 ) ;
memcpy ( s , & p , 12 ) ; // no warning
void * p1 = malloc ( 7 ) ;
char * a ;
memcpy ( & a , & p1 , sizeof a ) ;
// FIXME: No warning due to limitations imposed by current modelling of
// 'memcpy' (regions metadata is not copied).
int * ptrs [ 2 ] ;
int * allocated = ( int * ) malloc ( 4 ) ;
memcpy ( & ptrs [ 0 ] , & allocated , sizeof ( int * ) ) ;
// FIXME: No warning due to limitations imposed by current modelling of
// 'memcpy' (regions metadata is not copied).
}
void invalidateDestinationContents ( ) {
int * null = 0 ;
int * p = ( int * ) malloc ( 4 ) ;
memcpy ( & p , & null , sizeof ( int * ) ) ;
int * ptrs1 [ 2 ] ; // expected-warning {{Potential leak of memory pointed to by}}
ptrs1 [ 0 ] = ( int * ) malloc ( 4 ) ;
memcpy ( ptrs1 , & null , sizeof ( int * ) ) ;
int * ptrs2 [ 2 ] ; // expected-warning {{Potential memory leak}}
ptrs2 [ 0 ] = ( int * ) malloc ( 4 ) ;
memcpy ( & ptrs2 [ 1 ] , & null , sizeof ( int * ) ) ;
int * ptrs3 [ 2 ] ; // expected-warning {{Potential memory leak}}
ptrs3 [ 0 ] = ( int * ) malloc ( 4 ) ;
memcpy ( & ptrs3 [ 0 ] , & null , sizeof ( int * ) ) ;
} // expected-warning {{Potential memory leak}}
2012-04-14 14:01:31 +00:00
// Rely on the CString checker evaluation of the strcpy API to convey that the result of strcpy is equal to p.
void symbolLostWithStrcpy ( char * s ) {
char * p = malloc ( 12 ) ;
p = strcpy ( p , s ) ;
free ( p ) ;
}
// The same test as the one above, but with what is actually generated on a mac.
static __inline char *
__inline_strcpy_chk ( char * restrict __dest , const char * restrict __src )
{
return __builtin___strcpy_chk ( __dest , __src , __builtin_object_size ( __dest , 2 > 1 ) ) ;
}
void symbolLostWithStrcpy_InlineStrcpyVersion ( char * s ) {
char * p = malloc ( 12 ) ;
p = ( ( __builtin_object_size ( p , 0 ) ! = ( size_t ) - 1 ) ? __builtin___strcpy_chk ( p , s , __builtin_object_size ( p , 2 > 1 ) ) : __inline_strcpy_chk ( p , s ) ) ;
free ( p ) ;
}
// Here we are returning a pointer one past the allocated value. An idiom which
// can be used for implementing special malloc. The correct uses of this might
// be rare enough so that we could keep this as a warning.
static void * specialMalloc ( int n ) {
int * p ;
p = malloc ( n + 8 ) ;
if ( p ) {
p [ 0 ] = n ;
p + + ;
}
return p ;
}
// Potentially, the user could free the struct by performing pointer arithmetic on the return value.
// This is a variation of the specialMalloc issue, though probably would be more rare in correct code.
int * specialMallocWithStruct ( ) {
struct StructWithInt * px = malloc ( sizeof ( struct StructWithInt ) ) ;
return & ( px - > g ) ;
}
// Test various allocation/deallocation functions.
void testStrdup ( const char * s , unsigned validIndex ) {
char * s2 = strdup ( s ) ;
2013-04-08 18:45:10 +00:00
s2 [ validIndex + 1 ] = ' b ' ;
2013-06-10 20:45:12 +00:00
} // expected-warning {{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
int testStrndup ( const char * s , unsigned validIndex , unsigned size ) {
char * s2 = strndup ( s , size ) ;
s2 [ validIndex + 1 ] = ' b ' ;
if ( s2 [ validIndex ] ! = ' a ' )
return 0 ;
else
2013-06-10 20:45:12 +00:00
return 1 ; // expected-warning {{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
}
void testStrdupContentIsDefined ( const char * s , unsigned validIndex ) {
char * s2 = strdup ( s ) ;
char result = s2 [ 1 ] ; // no warning
free ( s2 ) ;
}
// ----------------------------------------------------------------------------
// Test the system library functions to which the pointer can escape.
// This tests false positive suppression.
// For now, we assume memory passed to pthread_specific escapes.
// TODO: We could check that if a new pthread binding is set, the existing
// binding must be freed; otherwise, a memory leak can occur.
void testPthereadSpecificEscape ( pthread_key_t key ) {
void * buf = malloc ( 12 ) ;
pthread_setspecific ( key , buf ) ; // no warning
}
// PR12101: Test funopen().
static int releasePtr ( void * _ctx ) {
free ( _ctx ) ;
return 0 ;
}
FILE * useFunOpen ( ) {
void * ctx = malloc ( sizeof ( int ) ) ;
FILE * f = funopen ( ctx , 0 , 0 , 0 , releasePtr ) ; // no warning
if ( f = = 0 ) {
free ( ctx ) ;
}
return f ;
}
FILE * useFunOpenNoReleaseFunction ( ) {
void * ctx = malloc ( sizeof ( int ) ) ;
FILE * f = funopen ( ctx , 0 , 0 , 0 , 0 ) ;
if ( f = = 0 ) {
free ( ctx ) ;
}
return f ; // expected-warning{{leak}}
}
2012-08-15 20:02:54 +00:00
static int readNothing ( void * _ctx , char * buf , int size ) {
return 0 ;
}
FILE * useFunOpenReadNoRelease ( ) {
void * ctx = malloc ( sizeof ( int ) ) ;
FILE * f = funopen ( ctx , readNothing , 0 , 0 , 0 ) ;
if ( f = = 0 ) {
free ( ctx ) ;
}
return f ; // expected-warning{{leak}}
}
2012-04-14 14:01:31 +00:00
// Test setbuf, setvbuf.
int my_main_no_warning ( ) {
char * p = malloc ( 100 ) ;
setvbuf ( stdout , p , 0 , 100 ) ;
return 0 ;
}
int my_main_no_warning2 ( ) {
char * p = malloc ( 100 ) ;
setbuf ( __stdoutp , p ) ;
return 0 ;
}
int my_main_warn ( FILE * f ) {
char * p = malloc ( 100 ) ;
setvbuf ( f , p , 0 , 100 ) ;
return 0 ; // expected-warning {{leak}}
}
// <rdar://problem/10978247>.
// some people use stack allocated memory as an optimization to avoid
// a heap allocation for small work sizes. This tests the analyzer's
// understanding that the malloc'ed memory is not the same as stackBuffer.
void radar10978247 ( int myValueSize ) {
char stackBuffer [ 128 ] ;
char * buffer ;
if ( myValueSize < = sizeof ( stackBuffer ) )
buffer = stackBuffer ;
else
buffer = malloc ( myValueSize ) ;
// do stuff with the buffer
if ( buffer ! = stackBuffer )
free ( buffer ) ;
}
void radar10978247_positive ( int myValueSize ) {
char stackBuffer [ 128 ] ;
char * buffer ;
if ( myValueSize < = sizeof ( stackBuffer ) )
buffer = stackBuffer ;
else
buffer = malloc ( myValueSize ) ;
// do stuff with the buffer
2013-04-08 18:45:10 +00:00
if ( buffer = = stackBuffer )
2012-04-14 14:01:31 +00:00
return ;
2013-04-08 18:45:10 +00:00
else
return ; // expected-warning {{leak}}
}
2012-08-15 20:02:54 +00:00
// <rdar://problem/11269741> Previously this triggered a false positive
// because malloc() is known to return uninitialized memory and the binding
// of 'o' to 'p->n' was not getting propertly handled. Now we report a leak.
struct rdar11269741_a_t {
struct rdar11269741_b_t {
int m ;
} n ;
} ;
int rdar11269741 ( struct rdar11269741_b_t o )
{
struct rdar11269741_a_t * p = ( struct rdar11269741_a_t * ) malloc ( sizeof ( * p ) ) ;
p - > n = o ;
return p - > n . m ; // expected-warning {{leak}}
}
// Pointer arithmetic, returning an ElementRegion.
void * radar11329382 ( unsigned bl ) {
void * ptr = malloc ( 16 ) ;
ptr = ptr + ( 2 - bl ) ;
return ptr ; // no warning
}
void __assert_rtn ( const char * , const char * , int , const char * ) __attribute__ ( ( __noreturn__ ) ) ;
int strcmp ( const char * , const char * ) ;
char * a ( void ) ;
void radar11270219 ( void ) {
char * x = a ( ) , * y = a ( ) ;
( __builtin_expect ( ! ( x & & y ) , 0 ) ? __assert_rtn ( __func__ , " /Users/zaks/tmp/ex.c " , 24 , " x && y " ) : ( void ) 0 ) ;
strcmp ( x , y ) ; // no warning
}
void radar_11358224_test_double_assign_ints_positive_2 ( )
{
void * ptr = malloc ( 16 ) ;
2013-04-08 18:45:10 +00:00
ptr = ptr ;
} // expected-warning {{leak}}
2012-08-15 20:02:54 +00:00
// Assume that functions which take a function pointer can free memory even if
// they are defined in system headers and take the const pointer to the
// allocated memory. (radar://11160612)
int const_ptr_and_callback ( int , const char * , int n , void ( * ) ( void * ) ) ;
void r11160612_1 ( ) {
char * x = malloc ( 12 ) ;
const_ptr_and_callback ( 0 , x , 12 , free ) ; // no - warning
}
// Null is passed as callback.
void r11160612_2 ( ) {
char * x = malloc ( 12 ) ;
2013-04-08 18:45:10 +00:00
const_ptr_and_callback ( 0 , x , 12 , 0 ) ;
} // expected-warning {{leak}}
2012-08-15 20:02:54 +00:00
// Callback is passed to a function defined in a system header.
void r11160612_4 ( ) {
char * x = malloc ( 12 ) ;
sqlite3_bind_text_my ( 0 , x , 12 , free ) ; // no - warning
}
// Passing callbacks in a struct.
void r11160612_5 ( StWithCallback St ) {
void * x = malloc ( 12 ) ;
dealocateMemWhenDoneByVal ( x , St ) ;
}
void r11160612_6 ( StWithCallback St ) {
void * x = malloc ( 12 ) ;
dealocateMemWhenDoneByRef ( & St , x ) ;
}
int mySub ( int , int ) ;
int myAdd ( int , int ) ;
int fPtr ( unsigned cond , int x ) {
return ( cond ? mySub : myAdd ) ( x , x ) ;
}
// Test anti-aliasing.
2012-04-14 14:01:31 +00:00
void dependsOnValueOfPtr ( int * g , unsigned f ) {
int * p ;
if ( f ) {
p = g ;
} else {
p = malloc ( 12 ) ;
}
if ( p ! = g )
free ( p ) ;
else
2012-08-15 20:02:54 +00:00
return ; // no warning
2012-04-14 14:01:31 +00:00
return ;
}
2012-08-15 20:02:54 +00:00
int CMPRegionHeapToStack ( ) {
int x = 0 ;
int * x1 = malloc ( 8 ) ;
int * x2 = & x ;
clang_analyzer_eval ( x1 = = x2 ) ; // expected-warning{{FALSE}}
free ( x1 ) ;
return x ;
}
int CMPRegionHeapToHeap2 ( ) {
int x = 0 ;
int * x1 = malloc ( 8 ) ;
int * x2 = malloc ( 8 ) ;
int * x4 = x1 ;
int * x5 = x2 ;
clang_analyzer_eval ( x4 = = x5 ) ; // expected-warning{{FALSE}}
free ( x1 ) ;
free ( x2 ) ;
return x ;
}
int CMPRegionHeapToHeap ( ) {
int x = 0 ;
int * x1 = malloc ( 8 ) ;
int * x4 = x1 ;
if ( x1 = = x4 ) {
free ( x1 ) ;
return 5 / x ; // expected-warning{{Division by zero}}
}
return x ; // expected-warning{{This statement is never executed}}
}
2012-04-14 14:01:31 +00:00
2012-08-15 20:02:54 +00:00
int HeapAssignment ( ) {
int m = 0 ;
int * x = malloc ( 4 ) ;
int * y = x ;
* x = 5 ;
clang_analyzer_eval ( * x ! = * y ) ; // expected-warning{{FALSE}}
free ( x ) ;
return 0 ;
}
int * retPtr ( ) ;
int * retPtrMightAlias ( int * x ) ;
int cmpHeapAllocationToUnknown ( ) {
int zero = 0 ;
int * yBefore = retPtr ( ) ;
int * m = malloc ( 8 ) ;
int * yAfter = retPtrMightAlias ( m ) ;
clang_analyzer_eval ( yBefore = = m ) ; // expected-warning{{FALSE}}
clang_analyzer_eval ( yAfter = = m ) ; // expected-warning{{FALSE}}
free ( m ) ;
return 0 ;
}
void localArrayTest ( ) {
char * p = ( char * ) malloc ( 12 ) ;
char * ArrayL [ 12 ] ;
2013-04-08 18:45:10 +00:00
ArrayL [ 0 ] = p ;
} // expected-warning {{leak}}
2012-08-15 20:02:54 +00:00
void localStructTest ( ) {
2012-04-14 14:01:31 +00:00
StructWithPtr St ;
StructWithPtr * pSt = & St ;
2013-04-08 18:45:10 +00:00
pSt - > memP = malloc ( 12 ) ;
2013-06-10 20:45:12 +00:00
} // expected-warning{{Potential leak of memory pointed to by}}
2012-04-14 14:01:31 +00:00
2013-04-08 18:45:10 +00:00
# ifdef __INTPTR_TYPE__
2012-08-15 20:02:54 +00:00
// Test double assignment through integers.
2013-04-08 18:45:10 +00:00
typedef __INTPTR_TYPE__ intptr_t ;
typedef unsigned __INTPTR_TYPE__ uintptr_t ;
static intptr_t glob ;
2012-08-15 20:02:54 +00:00
void test_double_assign_ints ( )
{
void * ptr = malloc ( 16 ) ; // no-warning
2013-04-08 18:45:10 +00:00
glob = ( intptr_t ) ( uintptr_t ) ptr ;
2012-08-15 20:02:54 +00:00
}
void test_double_assign_ints_positive ( )
{
void * ptr = malloc ( 16 ) ;
2013-04-08 18:45:10 +00:00
( void * ) ( intptr_t ) ( uintptr_t ) ptr ; // expected-warning {{unused}}
} // expected-warning {{leak}}
# endif
2012-08-15 20:02:54 +00:00
void testCGContextNoLeak ( )
{
void * ptr = malloc ( 16 ) ;
CGContextRef context = CGBitmapContextCreate ( ptr ) ;
// Because you can get the data back out like this, even much later,
// CGBitmapContextCreate is one of our "stop-tracking" exceptions.
free ( CGBitmapContextGetData ( context ) ) ;
}
void testCGContextLeak ( )
{
void * ptr = malloc ( 16 ) ;
CGContextRef context = CGBitmapContextCreate ( ptr ) ;
// However, this time we're just leaking the data, because the context
// object doesn't escape and it hasn't been freed in this function.
}
// Allow xpc context to escape. radar://11635258
// TODO: Would be great if we checked that the finalize_connection_context actually releases it.
static void finalize_connection_context ( void * ctx ) {
int * context = ctx ;
free ( context ) ;
}
void foo ( xpc_connection_t peer ) {
int * ctx = calloc ( 1 , sizeof ( int ) ) ;
xpc_connection_set_context ( peer , ctx ) ;
xpc_connection_set_finalizer_f ( peer , finalize_connection_context ) ;
xpc_connection_resume ( peer ) ;
}
// Make sure we catch errors when we free in a function which does not allocate memory.
void freeButNoMalloc ( int * p , int x ) {
if ( x ) {
free ( p ) ;
//user forgot a return here.
}
free ( p ) ; // expected-warning {{Attempt to free released memory}}
}
struct HasPtr {
2012-12-02 13:20:44 +00:00
char * p ;
2012-08-15 20:02:54 +00:00
} ;
2012-12-02 13:20:44 +00:00
char * reallocButNoMalloc ( struct HasPtr * a , int c , int size ) {
2012-08-15 20:02:54 +00:00
int * s ;
2012-12-02 13:20:44 +00:00
char * b = realloc ( a - > p , size ) ;
char * m = realloc ( a - > p , size ) ; // expected-warning {{Attempt to free released memory}}
2012-08-15 20:02:54 +00:00
return a - > p ;
}
2012-12-02 13:20:44 +00:00
// We should not warn in this case since the caller will presumably free a->p in all cases.
int reallocButNoMallocPR13674 ( struct HasPtr * a , int c , int size ) {
int * s ;
char * b = realloc ( a - > p , size ) ;
if ( b = = 0 )
return - 1 ;
a - > p = b ;
return 0 ;
}
// Test realloc with no visible malloc.
void * test ( void * ptr ) {
void * newPtr = realloc ( ptr , 4 ) ;
if ( newPtr = = 0 ) {
if ( ptr )
free ( ptr ) ; // no-warning
}
return newPtr ;
}
2013-04-08 18:45:10 +00:00
char * testLeakWithinReturn ( char * str ) {
return strdup ( strdup ( str ) ) ; // expected-warning{{leak}}
}
void passConstPtr ( const char * ptr ) ;
void testPassConstPointer ( ) {
char * string = malloc ( sizeof ( char ) * 10 ) ;
passConstPtr ( string ) ;
return ; // expected-warning {{leak}}
}
void testPassConstPointerIndirectly ( ) {
char * p = malloc ( 1 ) ;
p + + ;
memcmp ( p , p , sizeof ( & p ) ) ;
return ; // expected-warning {{leak}}
}
void testPassConstPointerIndirectlyStruct ( ) {
struct HasPtr hp ;
hp . p = malloc ( 10 ) ;
memcmp ( & hp , & hp , sizeof ( hp ) ) ;
2013-06-10 20:45:12 +00:00
return ; // expected-warning {{Potential leak of memory pointed to by 'hp.p'}}
2013-04-08 18:45:10 +00:00
}
void testPassToSystemHeaderFunctionIndirectlyStruct ( ) {
SomeStruct ss ;
ss . p = malloc ( 1 ) ;
2013-12-22 00:07:40 +00:00
fakeSystemHeaderCall ( & ss ) ; // invalidates ss, making ss.p unreachable
// Technically a false negative here -- we know the system function won't free
// ss.p, but nothing else will either!
} // no-warning
void testPassToSystemHeaderFunctionIndirectlyStructFree ( ) {
SomeStruct ss ;
ss . p = malloc ( 1 ) ;
fakeSystemHeaderCall ( & ss ) ; // invalidates ss, making ss.p unreachable
free ( ss . p ) ;
} // no-warning
void testPassToSystemHeaderFunctionIndirectlyArray ( ) {
int * p [ 1 ] ;
p [ 0 ] = malloc ( sizeof ( int ) ) ;
fakeSystemHeaderCallIntPtr ( p ) ; // invalidates p, making p[0] unreachable
// Technically a false negative here -- we know the system function won't free
// p[0], but nothing else will either!
} // no-warning
void testPassToSystemHeaderFunctionIndirectlyArrayFree ( ) {
int * p [ 1 ] ;
p [ 0 ] = malloc ( sizeof ( int ) ) ;
fakeSystemHeaderCallIntPtr ( p ) ; // invalidates p, making p[0] unreachable
free ( p [ 0 ] ) ;
} // no-warning
2013-04-08 18:45:10 +00:00
int * testOffsetAllocate ( size_t size ) {
int * memoryBlock = ( int * ) malloc ( size + sizeof ( int ) ) ;
return & memoryBlock [ 1 ] ; // no-warning
}
void testOffsetDeallocate ( int * memoryBlock ) {
free ( & memoryBlock [ - 1 ] ) ; // no-warning
}
void testOffsetOfRegionFreed ( ) {
__int64_t * array = malloc ( sizeof ( __int64_t ) * 2 ) ;
array + = 1 ;
free ( & array [ 0 ] ) ; // expected-warning{{Argument to free() is offset by 8 bytes from the start of memory allocated by malloc()}}
}
void testOffsetOfRegionFreed2 ( ) {
__int64_t * p = malloc ( sizeof ( __int64_t ) * 2 ) ;
p + = 1 ;
free ( p ) ; // expected-warning{{Argument to free() is offset by 8 bytes from the start of memory allocated by malloc()}}
}
void testOffsetOfRegionFreed3 ( ) {
char * r = malloc ( sizeof ( char ) ) ;
r = r - 10 ;
free ( r ) ; // expected-warning {{Argument to free() is offset by -10 bytes from the start of memory allocated by malloc()}}
}
void testOffsetOfRegionFreedAfterFunctionCall ( ) {
int * p = malloc ( sizeof ( int ) * 2 ) ;
p + = 1 ;
myfoo ( p ) ;
2013-06-10 20:45:12 +00:00
free ( p ) ; // expected-warning{{Argument to free() is offset by 4 bytes from the start of memory allocated by malloc()}}
2013-04-08 18:45:10 +00:00
}
void testFixManipulatedPointerBeforeFree ( ) {
int * array = malloc ( sizeof ( int ) * 2 ) ;
array + = 1 ;
free ( & array [ - 1 ] ) ; // no-warning
}
void testFixManipulatedPointerBeforeFree2 ( ) {
char * r = malloc ( sizeof ( char ) ) ;
r = r + 10 ;
free ( r - 10 ) ; // no-warning
}
void freeOffsetPointerPassedToFunction ( ) {
__int64_t * p = malloc ( sizeof ( __int64_t ) * 2 ) ;
p [ 1 ] = 0 ;
p + = 1 ;
myfooint ( * p ) ; // not passing the pointer, only a value pointed by pointer
free ( p ) ; // expected-warning {{Argument to free() is offset by 8 bytes from the start of memory allocated by malloc()}}
}
int arbitraryInt ( ) ;
void freeUnknownOffsetPointer ( ) {
char * r = malloc ( sizeof ( char ) ) ;
r = r + arbitraryInt ( ) ; // unable to reason about what the offset might be
free ( r ) ; // no-warning
}
void testFreeNonMallocPointerWithNoOffset ( ) {
char c ;
char * r = & c ;
r = r + 10 ;
free ( r - 10 ) ; // expected-warning {{Argument to free() is the address of the local variable 'c', which is not memory allocated by malloc()}}
}
void testFreeNonMallocPointerWithOffset ( ) {
char c ;
char * r = & c ;
free ( r + 1 ) ; // expected-warning {{Argument to free() is the address of the local variable 'c', which is not memory allocated by malloc()}}
}
void testOffsetZeroDoubleFree ( ) {
int * array = malloc ( sizeof ( int ) * 2 ) ;
int * p = & array [ 0 ] ;
free ( p ) ;
free ( & array [ 0 ] ) ; // expected-warning{{Attempt to free released memory}}
}
void testOffsetPassedToStrlen ( ) {
char * string = malloc ( sizeof ( char ) * 10 ) ;
string + = 1 ;
2013-06-10 20:45:12 +00:00
int length = strlen ( string ) ; // expected-warning {{Potential leak of memory pointed to by 'string'}}
2013-04-08 18:45:10 +00:00
}
void testOffsetPassedToStrlenThenFree ( ) {
char * string = malloc ( sizeof ( char ) * 10 ) ;
string + = 1 ;
int length = strlen ( string ) ;
free ( string ) ; // expected-warning {{Argument to free() is offset by 1 byte from the start of memory allocated by malloc()}}
}
void testOffsetPassedAsConst ( ) {
char * string = malloc ( sizeof ( char ) * 10 ) ;
string + = 1 ;
passConstPtr ( string ) ;
free ( string ) ; // expected-warning {{Argument to free() is offset by 1 byte from the start of memory allocated by malloc()}}
}
char * * _vectorSegments ;
int _nVectorSegments ;
void poolFreeC ( void * s ) {
free ( s ) ; // no-warning
}
void freeMemory ( ) {
while ( _nVectorSegments ) {
poolFreeC ( _vectorSegments [ _nVectorSegments + + ] ) ;
}
}
2013-12-22 00:07:40 +00:00
// PR16730
void testReallocEscaped ( void * * memory ) {
* memory = malloc ( 47 ) ;
char * new_memory = realloc ( * memory , 47 ) ;
if ( new_memory ! = 0 ) {
* memory = new_memory ;
}
}
// PR16558
void * smallocNoWarn ( size_t size ) {
if ( size = = 0 ) {
return malloc ( 1 ) ; // this branch is never called
}
else {
return malloc ( size ) ;
}
}
char * dupstrNoWarn ( const char * s ) {
const int len = strlen ( s ) ;
char * p = ( char * ) smallocNoWarn ( len + 1 ) ;
strcpy ( p , s ) ; // no-warning
return p ;
}
void * smallocWarn ( size_t size ) {
if ( size = = 2 ) {
return malloc ( 1 ) ;
}
else {
return malloc ( size ) ;
}
}
char * dupstrWarn ( const char * s ) {
const int len = strlen ( s ) ;
char * p = ( char * ) smallocWarn ( len + 1 ) ;
strcpy ( p , s ) ; // expected-warning{{String copy function overflows destination buffer}}
return p ;
}
int * radar15580979 ( ) {
int * data = ( int * ) malloc ( 32 ) ;
int * p = data ? : ( int * ) malloc ( 32 ) ; // no warning
return p ;
}
2012-08-15 20:02:54 +00:00
// ----------------------------------------------------------------------------
// False negatives.
2012-04-14 14:01:31 +00:00
void testMallocWithParam ( int * * p ) {
* p = ( int * ) malloc ( sizeof ( int ) ) ;
2013-04-08 18:45:10 +00:00
* p = 0 ; // FIXME: should warn here
2012-04-14 14:01:31 +00:00
}
void testMallocWithParam_2 ( int * * p ) {
2013-04-08 18:45:10 +00:00
* p = ( int * ) malloc ( sizeof ( int ) ) ; // no-warning
2012-04-14 14:01:31 +00:00
}
2013-12-22 00:07:40 +00:00
void testPassToSystemHeaderFunctionIndirectly ( ) {
int * p = malloc ( 4 ) ;
p + + ;
fakeSystemHeaderCallInt ( p ) ;
// FIXME: This is a leak: if we think a system function won't free p, it
// won't free (p-1) either.
}