File: assert.iterators.pass.cpp

package info (click to toggle)
llvm-toolchain-20 1%3A20.1.6-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,111,304 kB
  • sloc: cpp: 7,438,677; ansic: 1,393,822; asm: 1,012,926; python: 241,650; f90: 86,635; objc: 75,479; lisp: 42,144; pascal: 17,286; sh: 10,027; ml: 5,082; perl: 4,730; awk: 3,523; makefile: 3,349; javascript: 2,251; xml: 892; fortran: 672
file content (145 lines) | stat: -rw-r--r-- 5,232 bytes parent folder | download | duplicates (2)
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;
}