diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp index 599d4f306aa138..1a94ccdc2825a6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp @@ -58,6 +58,11 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS, DefinedOrUnknownSVal ElementCount = getDynamicElementCount( state, ER->getSuperRegion(), C.getSValBuilder(), ER->getValueType()); + // We assume that the location after the last element in the array is used as + // end() iterator. Reporting on these would return too many false positives. + if (Idx == ElementCount) + return; + ProgramStateRef StInBound = state->assumeInBound(Idx, ElementCount, true); ProgramStateRef StOutBound = state->assumeInBound(Idx, ElementCount, false); if (StOutBound && !StInBound) { @@ -70,7 +75,7 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS, // types explicitly reference such exploit categories (when applicable). if (!BT) BT.reset(new BuiltinBug( - this, "Return of pointer value outside of expected range", + this, "Buffer overflow", "Returned pointer value points outside the original object " "(potential buffer overflow)")); diff --git a/clang/test/Analysis/misc-ps-region-store.m b/clang/test/Analysis/misc-ps-region-store.m index b8710ff6f63818..9c31324e7e59de 100644 --- a/clang/test/Analysis/misc-ps-region-store.m +++ b/clang/test/Analysis/misc-ps-region-store.m @@ -463,7 +463,7 @@ void element_region_with_symbolic_superregion(int* p) { static int test_cwe466_return_outofbounds_pointer_a[10]; int *test_cwe466_return_outofbounds_pointer() { - int *p = test_cwe466_return_outofbounds_pointer_a+10; + int *p = test_cwe466_return_outofbounds_pointer_a+11; return p; // expected-warning{{Returned pointer value points outside the original object}} } diff --git a/clang/test/Analysis/return-ptr-range.cpp b/clang/test/Analysis/return-ptr-range.cpp index dd5dcd5d5d1948..9763b51264e6fb 100644 --- a/clang/test/Analysis/return-ptr-range.cpp +++ b/clang/test/Analysis/return-ptr-range.cpp @@ -25,3 +25,47 @@ int *test_element_index_lifetime_with_local_ptr() { } while (0); return local_ptr; // expected-warning{{Returned pointer value points outside the original object (potential buffer overflow)}} } + +template +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 +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 +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(); +}