1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.security.ReturnPtrRange -verify %s 2 3 int arr[10]; 4 int *ptr; 5 6 int conjure_index(); 7 test_element_index_lifetime()8int *test_element_index_lifetime() { 9 do { 10 int x = conjure_index(); 11 ptr = arr + x; 12 if (x != 20) 13 return arr; // no-warning 14 } while (0); 15 return ptr; // expected-warning{{Returned pointer value points outside the original object (potential buffer overflow)}} 16 } 17 test_element_index_lifetime_with_local_ptr()18int *test_element_index_lifetime_with_local_ptr() { 19 int *local_ptr; 20 do { 21 int x = conjure_index(); 22 local_ptr = arr + x; 23 if (x != 20) 24 return arr; // no-warning 25 } while (0); 26 return local_ptr; // expected-warning{{Returned pointer value points outside the original object (potential buffer overflow)}} 27 } 28 29 template <typename T, int N> 30 T* end(T (&arr)[N]) { 31 return arr + N; // no-warning, because we want to avoid false positives on returning the end() iterator of a container. 32 } 33 get_end_of_array()34void get_end_of_array() { 35 static int arr[10]; 36 end(arr); 37 } 38 39 template <int N> 40 class Iterable { 41 int buffer[N]; 42 int *start, *finish; 43 44 public: Iterable()45 Iterable() : start(buffer), finish(buffer + N) {} 46 begin()47 int* begin() { return start; } end()48 int* end() { return finish; } 49 }; 50 use_iterable_object()51void use_iterable_object() { 52 Iterable<20> iter; 53 iter.end(); 54 } 55 56 template <int N> 57 class BadIterable { 58 int buffer[N]; 59 int *start, *finish; 60 61 public: BadIterable()62 BadIterable() : start(buffer), finish(buffer + N) {} 63 begin()64 int* begin() { return start; } end()65 int* end() { return finish + 1; } // expected-warning{{Returned pointer value points outside the original object (potential buffer overflow)}} 66 }; 67 use_bad_iterable_object()68void use_bad_iterable_object() { 69 BadIterable<20> iter; 70 iter.end(); 71 } 72