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 //--------------------------------------------------
testMallocDoubleFree()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
testMallocLeak()15 void testMallocLeak() {
16 int *p = (int *)malloc(sizeof(int));
17 } // expected-warning{{Potential leak of memory pointed to by 'p'}}
18
testMallocUseAfterFree()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
testMallocBadFree()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
testMallocOffsetFree()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 //-----------------------------------------------------------------
testMismatchedDeallocator()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 //----------------------------------------------------------------
testNewDoubleFree()46 void testNewDoubleFree() {
47 int *p = new int;
48 delete p;
49 delete p; // expected-warning{{Attempt to free released memory}}
50 }
51
testNewLeak()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
testNewUseAfterFree()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
testNewBadFree()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
testNewOffsetFree()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
testMismatchedChangePtrThroughCall()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
testMismatchedChangePointeeThroughCall()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
testShouldReportDoubleFreeNotMismatched()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 }
allocIntArray(unsigned c)100 int *allocIntArray(unsigned c) {
101 return new int[c];
102 }
testMismatchedChangePointeeThroughAssignment()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