1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators-in-std-array
11 // UNSUPPORTED: libcpp-hardening-mode=none
12 // XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
16 // Make sure that std::array's iterators check for OOB accesses when the right hardening settings
23 #include "check_assertion.h"
25 template <typename Iter
>
26 void test_iterator(Iter begin
, Iter end
) {
27 std::ptrdiff_t distance
= std::distance(begin
, end
);
29 // Dereferencing an iterator at the end.
31 TEST_LIBCPP_ASSERT_FAILURE(*end
, "__static_bounded_iter::operator*: Attempt to dereference an iterator at the end");
32 TEST_LIBCPP_ASSERT_FAILURE(
33 end
.operator->(), "__static_bounded_iter::operator->: Attempt to dereference an iterator at the end");
36 // Incrementing an iterator past the end.
39 TEST_LIBCPP_ASSERT_FAILURE(it
++, "__static_bounded_iter::operator++: Attempt to advance an iterator past the end");
41 TEST_LIBCPP_ASSERT_FAILURE(++it
, "__static_bounded_iter::operator++: Attempt to advance an iterator past the end");
44 // Decrementing an iterator past the start.
47 TEST_LIBCPP_ASSERT_FAILURE(it
--, "__static_bounded_iter::operator--: Attempt to rewind an iterator past the start");
49 TEST_LIBCPP_ASSERT_FAILURE(--it
, "__static_bounded_iter::operator--: Attempt to rewind an iterator past the start");
52 // Advancing past the end with operator+= and operator+.
54 [[maybe_unused
]] const char* msg
= "__static_bounded_iter::operator+=: Attempt to advance an iterator past the end";
56 TEST_LIBCPP_ASSERT_FAILURE(it
+= 1, msg
);
57 TEST_LIBCPP_ASSERT_FAILURE(end
+ 1, msg
);
59 TEST_LIBCPP_ASSERT_FAILURE(it
+= (distance
+ 1), msg
);
60 TEST_LIBCPP_ASSERT_FAILURE(begin
+ (distance
+ 1), msg
);
63 // Advancing past the end with operator-= and operator-.
65 [[maybe_unused
]] const char* msg
= "__static_bounded_iter::operator-=: Attempt to advance an iterator past the end";
67 TEST_LIBCPP_ASSERT_FAILURE(it
-= (-1), msg
);
68 TEST_LIBCPP_ASSERT_FAILURE(end
- (-1), msg
);
70 TEST_LIBCPP_ASSERT_FAILURE(it
-= (-distance
- 1), msg
);
71 TEST_LIBCPP_ASSERT_FAILURE(begin
- (-distance
- 1), msg
);
74 // Rewinding past the start with operator+= and operator+.
76 [[maybe_unused
]] const char* msg
=
77 "__static_bounded_iter::operator+=: Attempt to rewind an iterator past the start";
79 TEST_LIBCPP_ASSERT_FAILURE(it
+= (-1), msg
);
80 TEST_LIBCPP_ASSERT_FAILURE(begin
+ (-1), msg
);
82 TEST_LIBCPP_ASSERT_FAILURE(it
+= (-distance
- 1), msg
);
83 TEST_LIBCPP_ASSERT_FAILURE(end
+ (-distance
- 1), msg
);
86 // Rewinding past the start with operator-= and operator-.
88 [[maybe_unused
]] const char* msg
=
89 "__static_bounded_iter::operator-=: Attempt to rewind an iterator past the start";
91 TEST_LIBCPP_ASSERT_FAILURE(it
-= 1, msg
);
92 TEST_LIBCPP_ASSERT_FAILURE(begin
- 1, msg
);
94 TEST_LIBCPP_ASSERT_FAILURE(it
-= (distance
+ 1), msg
);
95 TEST_LIBCPP_ASSERT_FAILURE(end
- (distance
+ 1), msg
);
98 // Out-of-bounds operator[].
100 [[maybe_unused
]] const char* end_msg
=
101 "__static_bounded_iter::operator[]: Attempt to index an iterator at or past the end";
102 [[maybe_unused
]] const char* past_end_msg
=
103 "__static_bounded_iter::operator[]: Attempt to index an iterator at or past the end";
104 [[maybe_unused
]] const char* past_start_msg
=
105 "__static_bounded_iter::operator[]: Attempt to index an iterator past the start";
106 TEST_LIBCPP_ASSERT_FAILURE(begin
[distance
], end_msg
);
107 TEST_LIBCPP_ASSERT_FAILURE(begin
[distance
+ 1], past_end_msg
);
108 TEST_LIBCPP_ASSERT_FAILURE(begin
[-1], past_start_msg
);
109 TEST_LIBCPP_ASSERT_FAILURE(begin
[-99], past_start_msg
);
113 TEST_LIBCPP_ASSERT_FAILURE(it
[distance
- 1], end_msg
);
114 TEST_LIBCPP_ASSERT_FAILURE(it
[distance
], past_end_msg
);
115 TEST_LIBCPP_ASSERT_FAILURE(it
[-2], past_start_msg
);
116 TEST_LIBCPP_ASSERT_FAILURE(it
[-99], past_start_msg
);
121 int main(int, char**) {
124 std::array
<int, 0> array
= {};
127 test_iterator(array
.begin(), array
.end());
129 // array::const_iterator
130 test_iterator(array
.cbegin(), array
.cend());
135 std::array
<int, 10> array
= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
138 test_iterator(array
.begin(), array
.end());
140 // array::const_iterator
141 test_iterator(array
.cbegin(), array
.cend());