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