1*ffe7950eSBalazs Benics // RUN: %clang_analyze_cc1 -verify \
2e5513336SKristóf Umann // RUN:   -analyzer-checker=core \
3e5513336SKristóf Umann // RUN:   -analyzer-checker=alpha.deadcode.UnreachableCode \
4e5513336SKristóf Umann // RUN:   -analyzer-checker=alpha.core.CastSize \
5e5513336SKristóf Umann // RUN:   -analyzer-checker=unix.Malloc \
6e5513336SKristóf Umann // RUN:   -analyzer-config unix.DynamicMemoryModeling:Optimistic=true %s
7e5513336SKristóf Umann 
8e5513336SKristóf Umann typedef __typeof(sizeof(int)) size_t;
9e5513336SKristóf Umann void *malloc(size_t);
10e5513336SKristóf Umann void free(void *);
11e5513336SKristóf Umann 
12e5513336SKristóf Umann struct MemoryAllocator {
13e5513336SKristóf Umann   void __attribute((ownership_returns(malloc))) * my_malloc(size_t);
14e5513336SKristóf Umann   void __attribute((ownership_takes(malloc, 2))) my_free(void *);
15e5513336SKristóf Umann   void __attribute((ownership_holds(malloc, 2))) my_hold(void *);
16e5513336SKristóf Umann };
17e5513336SKristóf Umann 
18e5513336SKristóf Umann void *myglobalpointer;
19e5513336SKristóf Umann 
20e5513336SKristóf Umann struct stuff {
21e5513336SKristóf Umann   void *somefield;
22e5513336SKristóf Umann };
23e5513336SKristóf Umann 
24e5513336SKristóf Umann struct stuff myglobalstuff;
25e5513336SKristóf Umann 
af1(MemoryAllocator & Alloc)26e5513336SKristóf Umann void af1(MemoryAllocator &Alloc) {
27e5513336SKristóf Umann   void *p = Alloc.my_malloc(12);
28e5513336SKristóf Umann   return; // expected-warning{{Potential leak of memory pointed to by}}
29e5513336SKristóf Umann }
30e5513336SKristóf Umann 
af1_b(MemoryAllocator & Alloc)31e5513336SKristóf Umann void af1_b(MemoryAllocator &Alloc) {
32e5513336SKristóf Umann   void *p = Alloc.my_malloc(12);
33e5513336SKristóf Umann } // expected-warning{{Potential leak of memory pointed to by}}
34e5513336SKristóf Umann 
af1_c(MemoryAllocator & Alloc)35e5513336SKristóf Umann void af1_c(MemoryAllocator &Alloc) {
36e5513336SKristóf Umann   myglobalpointer = Alloc.my_malloc(12); // no-warning
37e5513336SKristóf Umann }
38e5513336SKristóf Umann 
39e5513336SKristóf Umann // Test that we can pass out allocated memory via pointer-to-pointer.
af1_e(MemoryAllocator & Alloc,void ** pp)40e5513336SKristóf Umann void af1_e(MemoryAllocator &Alloc, void **pp) {
41e5513336SKristóf Umann   *pp = Alloc.my_malloc(42); // no-warning
42e5513336SKristóf Umann }
43e5513336SKristóf Umann 
af1_f(MemoryAllocator & Alloc,struct stuff * somestuff)44e5513336SKristóf Umann void af1_f(MemoryAllocator &Alloc, struct stuff *somestuff) {
45e5513336SKristóf Umann   somestuff->somefield = Alloc.my_malloc(12); // no-warning
46e5513336SKristóf Umann }
47e5513336SKristóf Umann 
48e5513336SKristóf Umann // Allocating memory for a field via multiple indirections to our arguments is OK.
af1_g(MemoryAllocator & Alloc,struct stuff ** pps)49e5513336SKristóf Umann void af1_g(MemoryAllocator &Alloc, struct stuff **pps) {
50e5513336SKristóf Umann   *pps = (struct stuff *)Alloc.my_malloc(sizeof(struct stuff)); // no-warning
51e5513336SKristóf Umann   (*pps)->somefield = Alloc.my_malloc(42); // no-warning
52e5513336SKristóf Umann }
53e5513336SKristóf Umann 
af2(MemoryAllocator & Alloc)54e5513336SKristóf Umann void af2(MemoryAllocator &Alloc) {
55e5513336SKristóf Umann   void *p = Alloc.my_malloc(12);
56e5513336SKristóf Umann   Alloc.my_free(p);
57e5513336SKristóf Umann   free(p); // expected-warning{{Attempt to free released memory}}
58e5513336SKristóf Umann }
59e5513336SKristóf Umann 
af2b(MemoryAllocator & Alloc)60e5513336SKristóf Umann void af2b(MemoryAllocator &Alloc) {
61e5513336SKristóf Umann   void *p = Alloc.my_malloc(12);
62e5513336SKristóf Umann   free(p);
63e5513336SKristóf Umann   Alloc.my_free(p); // expected-warning{{Attempt to free released memory}}
64e5513336SKristóf Umann }
65e5513336SKristóf Umann 
af2c(MemoryAllocator & Alloc)66e5513336SKristóf Umann void af2c(MemoryAllocator &Alloc) {
67e5513336SKristóf Umann   void *p = Alloc.my_malloc(12);
68e5513336SKristóf Umann   free(p);
69e5513336SKristóf Umann   Alloc.my_hold(p); // expected-warning{{Attempt to free released memory}}
70e5513336SKristóf Umann }
71e5513336SKristóf Umann 
72e5513336SKristóf Umann // No leak if malloc returns null.
af2e(MemoryAllocator & Alloc)73e5513336SKristóf Umann void af2e(MemoryAllocator &Alloc) {
74e5513336SKristóf Umann   void *p = Alloc.my_malloc(12);
75e5513336SKristóf Umann   if (!p)
76e5513336SKristóf Umann     return; // no-warning
77e5513336SKristóf Umann   free(p); // no-warning
78e5513336SKristóf Umann }
79e5513336SKristóf Umann 
80e5513336SKristóf Umann // This case inflicts a possible double-free.
af3(MemoryAllocator & Alloc)81e5513336SKristóf Umann void af3(MemoryAllocator &Alloc) {
82e5513336SKristóf Umann   void *p = Alloc.my_malloc(12);
83e5513336SKristóf Umann   Alloc.my_hold(p);
84e5513336SKristóf Umann   free(p); // expected-warning{{Attempt to free non-owned memory}}
85e5513336SKristóf Umann }
86e5513336SKristóf Umann 
af4(MemoryAllocator & Alloc)87e5513336SKristóf Umann void * af4(MemoryAllocator &Alloc) {
88e5513336SKristóf Umann   void *p = Alloc.my_malloc(12);
89e5513336SKristóf Umann   Alloc.my_free(p);
90e5513336SKristóf Umann   return p; // expected-warning{{Use of memory after it is freed}}
91e5513336SKristóf Umann }
92e5513336SKristóf Umann 
93e5513336SKristóf Umann // This case is (possibly) ok, be conservative
af5(MemoryAllocator & Alloc)94e5513336SKristóf Umann void * af5(MemoryAllocator &Alloc) {
95e5513336SKristóf Umann   void *p = Alloc.my_malloc(12);
96e5513336SKristóf Umann   Alloc.my_hold(p);
97e5513336SKristóf Umann   return p; // no-warning
98e5513336SKristóf Umann }
99e5513336SKristóf Umann 
100