Home | History | Annotate | Download | only in Analysis
      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