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