xref: /minix3/external/bsd/llvm/dist/clang/test/Analysis/malloc-interprocedural.c (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-inline-max-stack-depth=5 -verify %s
2*f4a2713aSLionel Sambuc 
3*f4a2713aSLionel Sambuc #include "Inputs/system-header-simulator.h"
4*f4a2713aSLionel Sambuc 
5*f4a2713aSLionel Sambuc void *malloc(size_t);
6*f4a2713aSLionel Sambuc void *valloc(size_t);
7*f4a2713aSLionel Sambuc void free(void *);
8*f4a2713aSLionel Sambuc void *realloc(void *ptr, size_t size);
9*f4a2713aSLionel Sambuc void *reallocf(void *ptr, size_t size);
10*f4a2713aSLionel Sambuc void *calloc(size_t nmemb, size_t size);
11*f4a2713aSLionel Sambuc 
12*f4a2713aSLionel Sambuc void exit(int) __attribute__ ((__noreturn__));
13*f4a2713aSLionel Sambuc void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
14*f4a2713aSLionel Sambuc size_t strlen(const char *);
15*f4a2713aSLionel Sambuc 
my_malloc1(void ** d,size_t size)16*f4a2713aSLionel Sambuc static void my_malloc1(void **d, size_t size) {
17*f4a2713aSLionel Sambuc   *d = malloc(size);
18*f4a2713aSLionel Sambuc }
19*f4a2713aSLionel Sambuc 
my_malloc2(int elevel,size_t size)20*f4a2713aSLionel Sambuc static void *my_malloc2(int elevel, size_t size) {
21*f4a2713aSLionel Sambuc   void     *data;
22*f4a2713aSLionel Sambuc   data = malloc(size);
23*f4a2713aSLionel Sambuc   if (data == 0)
24*f4a2713aSLionel Sambuc     exit(0);
25*f4a2713aSLionel Sambuc   return data;
26*f4a2713aSLionel Sambuc }
27*f4a2713aSLionel Sambuc 
my_free1(void * p)28*f4a2713aSLionel Sambuc static void my_free1(void *p) {
29*f4a2713aSLionel Sambuc   free(p);
30*f4a2713aSLionel Sambuc }
31*f4a2713aSLionel Sambuc 
test1()32*f4a2713aSLionel Sambuc static void test1() {
33*f4a2713aSLionel Sambuc   void *data = 0;
34*f4a2713aSLionel Sambuc   my_malloc1(&data, 4);
35*f4a2713aSLionel Sambuc } // expected-warning {{Potential leak of memory pointed to by 'data'}}
36*f4a2713aSLionel Sambuc 
test11()37*f4a2713aSLionel Sambuc static void test11() {
38*f4a2713aSLionel Sambuc   void *data = 0;
39*f4a2713aSLionel Sambuc   my_malloc1(&data, 4);
40*f4a2713aSLionel Sambuc   my_free1(data);
41*f4a2713aSLionel Sambuc }
42*f4a2713aSLionel Sambuc 
testUniqueingByallocationSiteInTopLevelFunction()43*f4a2713aSLionel Sambuc static void testUniqueingByallocationSiteInTopLevelFunction() {
44*f4a2713aSLionel Sambuc   void *data = my_malloc2(1, 4);
45*f4a2713aSLionel Sambuc   data = 0;
46*f4a2713aSLionel Sambuc   int x = 5;// expected-warning {{Potential leak of memory pointed to by 'data'}}
47*f4a2713aSLionel Sambuc   data = my_malloc2(1, 4);
48*f4a2713aSLionel Sambuc } // expected-warning {{Potential leak of memory pointed to by 'data'}}
49*f4a2713aSLionel Sambuc 
test3()50*f4a2713aSLionel Sambuc static void test3() {
51*f4a2713aSLionel Sambuc   void *data = my_malloc2(1, 4);
52*f4a2713aSLionel Sambuc   free(data);
53*f4a2713aSLionel Sambuc   data = my_malloc2(1, 4);
54*f4a2713aSLionel Sambuc   free(data);
55*f4a2713aSLionel Sambuc }
56*f4a2713aSLionel Sambuc 
test4()57*f4a2713aSLionel Sambuc int test4() {
58*f4a2713aSLionel Sambuc   int *data = (int*)my_malloc2(1, 4);
59*f4a2713aSLionel Sambuc   my_free1(data);
60*f4a2713aSLionel Sambuc   data = (int *)my_malloc2(1, 4);
61*f4a2713aSLionel Sambuc   my_free1(data);
62*f4a2713aSLionel Sambuc   return *data; // expected-warning {{Use of memory after it is freed}}
63*f4a2713aSLionel Sambuc }
64*f4a2713aSLionel Sambuc 
test6()65*f4a2713aSLionel Sambuc void test6() {
66*f4a2713aSLionel Sambuc   int *data = (int *)my_malloc2(1, 4);
67*f4a2713aSLionel Sambuc   my_free1((int*)data);
68*f4a2713aSLionel Sambuc   my_free1((int*)data); // expected-warning{{Use of memory after it is freed}}
69*f4a2713aSLionel Sambuc }
70*f4a2713aSLionel Sambuc 
71*f4a2713aSLionel Sambuc // TODO: We should warn here.
test5()72*f4a2713aSLionel Sambuc void test5() {
73*f4a2713aSLionel Sambuc   int *data;
74*f4a2713aSLionel Sambuc   my_free1((int*)data);
75*f4a2713aSLionel Sambuc }
76*f4a2713aSLionel Sambuc 
reshape(char * in)77*f4a2713aSLionel Sambuc static char *reshape(char *in) {
78*f4a2713aSLionel Sambuc     return 0;
79*f4a2713aSLionel Sambuc }
80*f4a2713aSLionel Sambuc 
testThatRemoveDeadBindingsRunBeforeEachCall()81*f4a2713aSLionel Sambuc void testThatRemoveDeadBindingsRunBeforeEachCall() {
82*f4a2713aSLionel Sambuc     char *v = malloc(12);
83*f4a2713aSLionel Sambuc     v = reshape(v);
84*f4a2713aSLionel Sambuc     v = reshape(v);// expected-warning {{Potential leak of memory pointed to by 'v'}}
85*f4a2713aSLionel Sambuc }
86*f4a2713aSLionel Sambuc 
87*f4a2713aSLionel Sambuc // Test that we keep processing after 'return;'
fooWithEmptyReturn(int x)88*f4a2713aSLionel Sambuc void fooWithEmptyReturn(int x) {
89*f4a2713aSLionel Sambuc   if (x)
90*f4a2713aSLionel Sambuc     return;
91*f4a2713aSLionel Sambuc   x++;
92*f4a2713aSLionel Sambuc   return;
93*f4a2713aSLionel Sambuc }
94*f4a2713aSLionel Sambuc 
uafAndCallsFooWithEmptyReturn()95*f4a2713aSLionel Sambuc int uafAndCallsFooWithEmptyReturn() {
96*f4a2713aSLionel Sambuc   int *x = (int*)malloc(12);
97*f4a2713aSLionel Sambuc   free(x);
98*f4a2713aSLionel Sambuc   fooWithEmptyReturn(12);
99*f4a2713aSLionel Sambuc   return *x; // expected-warning {{Use of memory after it is freed}}
100*f4a2713aSLionel Sambuc }
101*f4a2713aSLionel Sambuc 
102*f4a2713aSLionel Sambuc 
103*f4a2713aSLionel Sambuc // If we inline any of the malloc-family functions, the checker shouldn't also
104*f4a2713aSLionel Sambuc // try to do additional modeling. <rdar://problem/12317671>
strndup(const char * str,size_t n)105*f4a2713aSLionel Sambuc char *strndup(const char *str, size_t n) {
106*f4a2713aSLionel Sambuc   if (!str)
107*f4a2713aSLionel Sambuc     return 0;
108*f4a2713aSLionel Sambuc 
109*f4a2713aSLionel Sambuc   // DO NOT FIX. This is to test that we are actually using the inlined
110*f4a2713aSLionel Sambuc   // behavior!
111*f4a2713aSLionel Sambuc   if (n < 5)
112*f4a2713aSLionel Sambuc     return 0;
113*f4a2713aSLionel Sambuc 
114*f4a2713aSLionel Sambuc   size_t length = strlen(str);
115*f4a2713aSLionel Sambuc   if (length < n)
116*f4a2713aSLionel Sambuc     n = length;
117*f4a2713aSLionel Sambuc 
118*f4a2713aSLionel Sambuc   char *result = malloc(n + 1);
119*f4a2713aSLionel Sambuc   memcpy(result, str, n);
120*f4a2713aSLionel Sambuc   result[n] = '\0';
121*f4a2713aSLionel Sambuc   return result;
122*f4a2713aSLionel Sambuc }
123*f4a2713aSLionel Sambuc 
useStrndup(size_t n)124*f4a2713aSLionel Sambuc void useStrndup(size_t n) {
125*f4a2713aSLionel Sambuc   if (n == 0) {
126*f4a2713aSLionel Sambuc     (void)strndup(0, 20); // no-warning
127*f4a2713aSLionel Sambuc     return;
128*f4a2713aSLionel Sambuc   } else if (n < 5) {
129*f4a2713aSLionel Sambuc     (void)strndup("hi there", n); // no-warning
130*f4a2713aSLionel Sambuc     return;
131*f4a2713aSLionel Sambuc   } else {
132*f4a2713aSLionel Sambuc     (void)strndup("hi there", n);
133*f4a2713aSLionel Sambuc     return; // expected-warning{{leak}}
134*f4a2713aSLionel Sambuc   }
135*f4a2713aSLionel Sambuc }
136