1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.security.ReturnPtrRange -analyzer-output text -verify %s 2 3 int conjure_index(); 4 5 namespace test_element_index_lifetime { 6 7 int arr[10]; // expected-note{{Original object declared here}} expected-note{{Original object declared here}} 8 int *ptr; 9 10 int *test_global_ptr() { 11 do { // expected-note{{Loop condition is false. Exiting loop}} 12 int x = conjure_index(); 13 ptr = arr + x; // expected-note{{Value assigned to 'ptr'}} 14 if (x != 20) // expected-note{{Assuming 'x' is equal to 20}} 15 // expected-note@-1{{Taking false branch}} 16 return arr; // no-warning 17 } while(0); 18 return ptr; // expected-warning{{Returned pointer value points outside the original object (potential buffer overflow) [alpha.security.ReturnPtrRange]}} 19 // expected-note@-1{{Returned pointer value points outside the original object (potential buffer overflow)}} 20 // expected-note@-2{{Original object 'arr' is an array of 10 'int' objects}} 21 } 22 23 int *test_local_ptr() { 24 int *local_ptr; 25 do { // expected-note{{Loop condition is false. Exiting loop}} 26 int x = conjure_index(); 27 local_ptr = arr + x; // expected-note{{Value assigned to 'local_ptr'}} 28 if (x != 20) // expected-note{{Assuming 'x' is equal to 20}} 29 // expected-note@-1{{Taking false branch}} 30 return arr; // no-warning 31 } while(0); 32 return local_ptr; // expected-warning{{Returned pointer value points outside the original object (potential buffer overflow) [alpha.security.ReturnPtrRange]}} 33 // expected-note@-1{{Returned pointer value points outside the original object (potential buffer overflow)}} 34 // expected-note@-2{{Original object 'arr' is an array of 10 'int' objects}} 35 } 36 37 } 38 39 template <typename T, int N> 40 T* end(T (&arr)[N]) { 41 return arr + N; // no-warning, because we want to avoid false positives on returning the end() iterator of a container. 42 } 43 44 void get_end_of_array() { 45 static int arr[10]; 46 end(arr); 47 } 48 49 template <int N> 50 class Iterable { 51 int buffer[N]; 52 int *start, *finish; 53 54 public: 55 Iterable() : start(buffer), finish(buffer + N) {} 56 57 int* begin() { return start; } 58 int* end() { return finish; } 59 }; 60 61 void use_iterable_object() { 62 Iterable<20> iter; 63 iter.end(); 64 } 65 66 template <int N> 67 class BadIterable { 68 int buffer[N]; // expected-note{{Original object declared here}} 69 int *start, *finish; 70 71 public: 72 BadIterable() : start(buffer), finish(buffer + N) {} // expected-note{{Value assigned to 'iter.finish'}} 73 74 int* begin() { return start; } 75 int* end() { return finish + 1; } // expected-warning{{Returned pointer value points outside the original object}} 76 // expected-note@-1{{Returned pointer value points outside the original object}} 77 // expected-note@-2{{Original object 'buffer' is an array of 20 'int' objects, returned pointer points at index 21}} 78 }; 79 80 void use_bad_iterable_object() { 81 BadIterable<20> iter; // expected-note{{Calling default constructor for 'BadIterable<20>'}} 82 // expected-note@-1{{Returning from default constructor for 'BadIterable<20>'}} 83 iter.end(); // expected-note{{Calling 'BadIterable::end'}} 84 } 85 86 int *test_idx_sym(int I) { 87 static int arr[10]; // expected-note{{Original object declared here}} expected-note{{'arr' initialized here}} 88 89 if (I != 11) // expected-note{{Assuming 'I' is equal to 11}} 90 // expected-note@-1{{Taking false branch}} 91 return arr; 92 return arr + I; // expected-warning{{Returned pointer value points outside the original object}} 93 // expected-note@-1{{Returned pointer value points outside the original object}} 94 // expected-note@-2{{Original object 'arr' is an array of 10 'int' objects, returned pointer points at index 11}} 95 } 96 97 namespace test_array_of_struct { 98 99 struct Data { 100 int A; 101 char *B; 102 }; 103 104 Data DataArr[10]; // expected-note{{Original object declared here}} 105 106 Data *test_struct_array() { 107 int I = conjure_index(); 108 if (I != 11) // expected-note{{Assuming 'I' is equal to 11}} 109 // expected-note@-1{{Taking false branch}} 110 return DataArr; 111 return DataArr + I; // expected-warning{{Returned pointer value points outside the original object}} 112 // expected-note@-1{{Returned pointer value points outside the original object}} 113 // expected-note@-2{{Original object 'DataArr' is an array of 10 'test_array_of_struct::Data' objects, returned pointer points at index 11}} 114 } 115 116 } 117 118