1// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,cplusplus.NewDelete -std=c++11 -verify %s 2// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,cplusplus.NewDelete,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s 3 4#include "Inputs/system-header-simulator-for-malloc.h" 5 6//-------------------------------------------------- 7// Check that unix.Malloc catches all types of bugs. 8//-------------------------------------------------- 9void testMallocDoubleFree() { 10 int *p = (int *)malloc(sizeof(int)); 11 free(p); 12 free(p); // expected-warning{{Attempt to free released memory}} 13} 14 15void testMallocLeak() { 16 int *p = (int *)malloc(sizeof(int)); 17} // expected-warning{{Potential leak of memory pointed to by 'p'}} 18 19void testMallocUseAfterFree() { 20 int *p = (int *)malloc(sizeof(int)); 21 free(p); 22 int j = *p; // expected-warning{{Use of memory after it is freed}} 23} 24 25void testMallocBadFree() { 26 int i; 27 free(&i); // expected-warning{{Argument to free() is the address of the local variable 'i', which is not memory allocated by malloc()}} 28} 29 30void testMallocOffsetFree() { 31 int *p = (int *)malloc(sizeof(int)); 32 free(++p); // expected-warning{{Argument to free() is offset by 4 bytes from the start of memory allocated by malloc()}} 33} 34 35//----------------------------------------------------------------- 36// Check that unix.MismatchedDeallocator catches all types of bugs. 37//----------------------------------------------------------------- 38void testMismatchedDeallocator() { 39 int *x = (int *)malloc(sizeof(int)); 40 delete x; // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not 'delete'}} 41} 42 43//---------------------------------------------------------------- 44// Check that alpha.cplusplus.NewDelete catches all types of bugs. 45//---------------------------------------------------------------- 46void testNewDoubleFree() { 47 int *p = new int; 48 delete p; 49 delete p; // expected-warning{{Attempt to free released memory}} 50} 51 52void testNewLeak() { 53 int *p = new int; 54} 55#ifdef LEAKS 56// expected-warning@-2 {{Potential leak of memory pointed to by 'p'}} 57#endif 58 59void testNewUseAfterFree() { 60 int *p = (int *)operator new(0); 61 delete p; 62 int j = *p; // expected-warning{{Use of memory after it is freed}} 63} 64 65void testNewBadFree() { 66 int i; 67 delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}} 68} 69 70void testNewOffsetFree() { 71 int *p = new int; 72 operator delete(++p); // expected-warning{{Argument to operator delete is offset by 4 bytes from the start of memory allocated by 'new'}} 73} 74 75//---------------------------------------------------------------- 76// Test that we check for free errors on escaped pointers. 77//---------------------------------------------------------------- 78void changePtr(int **p); 79static int *globalPtr; 80void changePointee(int *p); 81 82void testMismatchedChangePtrThroughCall() { 83 int *p = (int*)malloc(sizeof(int)*4); 84 changePtr(&p); 85 delete p; // no-warning the value of the pointer might have changed 86} 87 88void testMismatchedChangePointeeThroughCall() { 89 int *p = (int*)malloc(sizeof(int)*4); 90 changePointee(p); 91 delete p; // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not 'delete'}} 92} 93 94void testShouldReportDoubleFreeNotMismatched() { 95 int *p = (int*)malloc(sizeof(int)*4); 96 globalPtr = p; 97 free(p); 98 delete globalPtr; // expected-warning {{Attempt to free released memory}} 99} 100int *allocIntArray(unsigned c) { 101 return new int[c]; 102} 103void testMismatchedChangePointeeThroughAssignment() { 104 int *arr = allocIntArray(4); 105 globalPtr = arr; 106 delete arr; // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}} 107} 108