blob: 9763b51264e6fbb2aa1ffeb197ebac527d3884fb [file] [log] [blame]
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.security.ReturnPtrRange -verify %s
int arr[10];
int *ptr;
int conjure_index();
int *test_element_index_lifetime() {
do {
int x = conjure_index();
ptr = arr + x;
if (x != 20)
return arr; // no-warning
} while (0);
return ptr; // expected-warning{{Returned pointer value points outside the original object (potential buffer overflow)}}
}
int *test_element_index_lifetime_with_local_ptr() {
int *local_ptr;
do {
int x = conjure_index();
local_ptr = arr + x;
if (x != 20)
return arr; // no-warning
} while (0);
return local_ptr; // expected-warning{{Returned pointer value points outside the original object (potential buffer overflow)}}
}
template <typename T, int N>
T* end(T (&arr)[N]) {
return arr + N; // no-warning, because we want to avoid false positives on returning the end() iterator of a container.
}
void get_end_of_array() {
static int arr[10];
end(arr);
}
template <int N>
class Iterable {
int buffer[N];
int *start, *finish;
public:
Iterable() : start(buffer), finish(buffer + N) {}
int* begin() { return start; }
int* end() { return finish; }
};
void use_iterable_object() {
Iterable<20> iter;
iter.end();
}
template <int N>
class BadIterable {
int buffer[N];
int *start, *finish;
public:
BadIterable() : start(buffer), finish(buffer + N) {}
int* begin() { return start; }
int* end() { return finish + 1; } // expected-warning{{Returned pointer value points outside the original object (potential buffer overflow)}}
};
void use_bad_iterable_object() {
BadIterable<20> iter;
iter.end();
}