1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators-in-std-array
// UNSUPPORTED: c++03
// UNSUPPORTED: libcpp-hardening-mode=none
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// <array>
// Make sure that std::array's iterators check for OOB accesses when the right hardening settings
// are enabled.
#include <array>
#include <cstddef>
#include <iterator>
#include "check_assertion.h"
template <typename Iter>
void test_iterator(Iter begin, Iter end) {
std::ptrdiff_t distance = std::distance(begin, end);
// Dereferencing an iterator at the end.
{
TEST_LIBCPP_ASSERT_FAILURE(*end, "__static_bounded_iter::operator*: Attempt to dereference an iterator at the end");
TEST_LIBCPP_ASSERT_FAILURE(
end.operator->(), "__static_bounded_iter::operator->: Attempt to dereference an iterator at the end");
}
// Incrementing an iterator past the end.
{
auto it = end;
TEST_LIBCPP_ASSERT_FAILURE(it++, "__static_bounded_iter::operator++: Attempt to advance an iterator past the end");
it = end;
TEST_LIBCPP_ASSERT_FAILURE(++it, "__static_bounded_iter::operator++: Attempt to advance an iterator past the end");
}
// Decrementing an iterator past the start.
{
auto it = begin;
TEST_LIBCPP_ASSERT_FAILURE(it--, "__static_bounded_iter::operator--: Attempt to rewind an iterator past the start");
it = begin;
TEST_LIBCPP_ASSERT_FAILURE(--it, "__static_bounded_iter::operator--: Attempt to rewind an iterator past the start");
}
// Advancing past the end with operator+= and operator+.
{
[[maybe_unused]] const char* msg = "__static_bounded_iter::operator+=: Attempt to advance an iterator past the end";
auto it = end;
TEST_LIBCPP_ASSERT_FAILURE(it += 1, msg);
TEST_LIBCPP_ASSERT_FAILURE(end + 1, msg);
it = begin;
TEST_LIBCPP_ASSERT_FAILURE(it += (distance + 1), msg);
TEST_LIBCPP_ASSERT_FAILURE(begin + (distance + 1), msg);
}
// Advancing past the end with operator-= and operator-.
{
[[maybe_unused]] const char* msg = "__static_bounded_iter::operator-=: Attempt to advance an iterator past the end";
auto it = end;
TEST_LIBCPP_ASSERT_FAILURE(it -= (-1), msg);
TEST_LIBCPP_ASSERT_FAILURE(end - (-1), msg);
it = begin;
TEST_LIBCPP_ASSERT_FAILURE(it -= (-distance - 1), msg);
TEST_LIBCPP_ASSERT_FAILURE(begin - (-distance - 1), msg);
}
// Rewinding past the start with operator+= and operator+.
{
[[maybe_unused]] const char* msg =
"__static_bounded_iter::operator+=: Attempt to rewind an iterator past the start";
auto it = begin;
TEST_LIBCPP_ASSERT_FAILURE(it += (-1), msg);
TEST_LIBCPP_ASSERT_FAILURE(begin + (-1), msg);
it = end;
TEST_LIBCPP_ASSERT_FAILURE(it += (-distance - 1), msg);
TEST_LIBCPP_ASSERT_FAILURE(end + (-distance - 1), msg);
}
// Rewinding past the start with operator-= and operator-.
{
[[maybe_unused]] const char* msg =
"__static_bounded_iter::operator-=: Attempt to rewind an iterator past the start";
auto it = begin;
TEST_LIBCPP_ASSERT_FAILURE(it -= 1, msg);
TEST_LIBCPP_ASSERT_FAILURE(begin - 1, msg);
it = end;
TEST_LIBCPP_ASSERT_FAILURE(it -= (distance + 1), msg);
TEST_LIBCPP_ASSERT_FAILURE(end - (distance + 1), msg);
}
// Out-of-bounds operator[].
{
[[maybe_unused]] const char* end_msg =
"__static_bounded_iter::operator[]: Attempt to index an iterator at or past the end";
[[maybe_unused]] const char* past_end_msg =
"__static_bounded_iter::operator[]: Attempt to index an iterator at or past the end";
[[maybe_unused]] const char* past_start_msg =
"__static_bounded_iter::operator[]: Attempt to index an iterator past the start";
TEST_LIBCPP_ASSERT_FAILURE(begin[distance], end_msg);
TEST_LIBCPP_ASSERT_FAILURE(begin[distance + 1], past_end_msg);
TEST_LIBCPP_ASSERT_FAILURE(begin[-1], past_start_msg);
TEST_LIBCPP_ASSERT_FAILURE(begin[-99], past_start_msg);
if (distance > 0) {
auto it = begin + 1;
TEST_LIBCPP_ASSERT_FAILURE(it[distance - 1], end_msg);
TEST_LIBCPP_ASSERT_FAILURE(it[distance], past_end_msg);
TEST_LIBCPP_ASSERT_FAILURE(it[-2], past_start_msg);
TEST_LIBCPP_ASSERT_FAILURE(it[-99], past_start_msg);
}
}
}
int main(int, char**) {
// Empty array
{
std::array<int, 0> array = {};
// array::iterator
test_iterator(array.begin(), array.end());
// array::const_iterator
test_iterator(array.cbegin(), array.cend());
}
// Non-empty array
{
std::array<int, 10> array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// array::iterator
test_iterator(array.begin(), array.end());
// array::const_iterator
test_iterator(array.cbegin(), array.cend());
}
return 0;
}
|