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