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 //-------------------------------------------------- 9 void testMallocDoubleFree() { 10 int *p = (int *)malloc(sizeof(int)); 11 free(p); 12 free(p); // expected-warning{{Attempt to free released memory}} 13 } 14 15 void testMallocLeak() { 16 int *p = (int *)malloc(sizeof(int)); 17 } // expected-warning{{Potential leak of memory pointed to by 'p'}} 18 19 void 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 25 void 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 30 void 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 //----------------------------------------------------------------- 38 void 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 //---------------------------------------------------------------- 46 void testNewDoubleFree() { 47 int *p = new int; 48 delete p; 49 delete p; // expected-warning{{Attempt to free released memory}} 50 } 51 52 void 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 59 void 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 65 void 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 70 void 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 //---------------------------------------------------------------- 78 void changePtr(int **p); 79 static int *globalPtr; 80 void changePointee(int *p); 81 82 void 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 88 void 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 94 void 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 } 100 int *allocIntArray(unsigned c) { 101 return new int[c]; 102 } 103 void 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