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 Umannvoid 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 Umannvoid 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 Umannvoid 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 Umannvoid 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 Umannvoid 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 Umannvoid 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 Umannvoid 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 Umannvoid 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 Umannvoid 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 Umannvoid 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 Umannvoid 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 Umannvoid * 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 Umannvoid * 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