xref: /llvm-project/clang/test/Analysis/free.c (revision 893a303962608469ec5bd01fe44e82c935152e9c)
1 // RUN: %clang_analyze_cc1 -fblocks -verify %s \
2 // RUN:   -analyzer-checker=core \
3 // RUN:   -analyzer-checker=unix.Malloc
4 //
5 // RUN: %clang_analyze_cc1 -fblocks -verify %s \
6 // RUN:   -analyzer-checker=core \
7 // RUN:   -analyzer-checker=unix.Malloc \
8 // RUN:   -analyzer-config unix.DynamicMemoryModeling:Optimistic=true
9 typedef __typeof(sizeof(int)) size_t;
10 void free(void *);
11 void *alloca(size_t);
12 
13 void t1 (void) {
14   int a[] = { 1 };
15   free(a);
16   // expected-warning@-1{{Argument to 'free()' is the address of the local variable 'a', which is not memory allocated by 'malloc()'}}
17   // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
18 }
19 
20 void t2 (void) {
21   int a = 1;
22   free(&a);
23   // expected-warning@-1{{Argument to 'free()' is the address of the local variable 'a', which is not memory allocated by 'malloc()'}}
24   // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
25 }
26 
27 void t3 (void) {
28   static int a[] = { 1 };
29   free(a);
30   // expected-warning@-1{{Argument to 'free()' is the address of the static variable 'a', which is not memory allocated by 'malloc()'}}
31   // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
32 }
33 
34 void t4 (char *x) {
35   free(x); // no-warning
36 }
37 
38 void t5 (void) {
39   extern char *ptr(void);
40   free(ptr()); // no-warning
41 }
42 
43 void t6 (void) {
44   free((void*)1000);
45   // expected-warning@-1{{Argument to 'free()' is a constant address (1000), which is not memory allocated by 'malloc()'}}
46   // expected-warning@-2{{attempt to call free on non-heap object '(void *)1000'}}
47 }
48 
49 void t7 (char **x) {
50   free(*x); // no-warning
51 }
52 
53 void t8 (char **x) {
54   // ugh
55   free((*x)+8); // no-warning
56 }
57 
58 void t9 (void) {
59 label:
60   free(&&label);
61   // expected-warning@-1{{Argument to 'free()' is the address of the label 'label', which is not memory allocated by 'malloc()'}}
62   // expected-warning@-2{{attempt to call free on non-heap object 'label'}}
63 }
64 
65 void t10 (void) {
66   free((void*)&t10);
67   // expected-warning@-1{{Argument to 'free()' is the address of the function 't10', which is not memory allocated by 'malloc()'}}
68   // expected-warning@-2{{attempt to call free on non-heap object 't10'}}
69 }
70 
71 void t11 (void) {
72   char *p = (char*)alloca(2);
73   free(p); // expected-warning {{Memory allocated by 'alloca()' should not be deallocated}}
74 }
75 
76 void t12 (void) {
77   char *p = (char*)__builtin_alloca(2);
78   free(p); // expected-warning {{Memory allocated by 'alloca()' should not be deallocated}}
79 }
80 
81 void t13 (void) {
82   free(^{return;});
83   // expected-warning@-1{{Argument to 'free()' is a block, which is not memory allocated by 'malloc()'}}
84   // expected-warning@-2{{attempt to call free on non-heap object: block expression}}
85 }
86 
87 void t14 (char a) {
88   free(&a);
89   // expected-warning@-1{{Argument to 'free()' is the address of the parameter 'a', which is not memory allocated by 'malloc()'}}
90   // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
91 }
92 
93 static int someGlobal[2];
94 void t15 (void) {
95   free(someGlobal);
96   // expected-warning@-1{{Argument to 'free()' is the address of the global variable 'someGlobal', which is not memory allocated by 'malloc()'}}
97   // expected-warning@-2{{attempt to call free on non-heap object 'someGlobal'}}
98 }
99 
100 void t16 (char **x, int offset) {
101   // Unknown value
102   free(x[offset]); // no-warning
103 }
104 
105 int *iptr(void);
106 void t17(void) {
107   free(iptr); // Oops, forgot to call iptr().
108   // expected-warning@-1{{Argument to 'free()' is the address of the function 'iptr', which is not memory allocated by 'malloc()'}}
109   // expected-warning@-2{{attempt to call free on non-heap object 'iptr'}}
110 }
111 
112 struct S {
113   const char* p;
114 };
115 
116 void t18 (struct S s) {
117   free((void*)(unsigned long long)s.p); // no warning
118 }
119