brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · 85e2df1 Raw
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