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()8 int *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()18 int *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()34 void 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()51 void 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()68 void use_bad_iterable_object() {
69   BadIterable<20> iter;
70   iter.end();
71 }
72