]> git.saurik.com Git - apple/xnu.git/blob - tests/bounded_ptr_src/deref.cpp
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tests / bounded_ptr_src / deref.cpp
1 //
2 // Tests for
3 // T& operator*() const;
4 // T* operator->() const;
5 //
6
7 #include <libkern/c++/bounded_ptr.h>
8 #include <array>
9 #include <darwintest.h>
10 #include <darwintest_utils.h>
11 #include "test_utils.h"
12
13 #define _assert(...) T_ASSERT_TRUE((__VA_ARGS__), # __VA_ARGS__)
14
15 struct T {
16 int i;
17 friend constexpr bool
18 operator==(T const volatile& a, T const& b)
19 {
20 return a.i == b.i;
21 }
22 };
23
24 namespace {
25 struct tracking_policy {
26 static bool did_trap;
27 static void
28 trap(char const*)
29 {
30 did_trap = true;
31 }
32 };
33 bool tracking_policy::did_trap = false;
34 }
35
36 template <typename T, typename QualT>
37 static void
38 tests()
39 {
40 std::array<T, 5> array = {T{0}, T{1}, T{2}, T{3}, T{4}};
41
42 {
43 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
44 // ^ ^
45 // | |
46 // begin, ptr end
47 test_bounded_ptr<QualT> ptr(array.begin() + 0, array.begin(), array.end());
48 QualT& ref = *ptr;
49 _assert(ref == T{0});
50 _assert(&ref == &array[0]);
51
52 _assert(ptr->i == 0);
53 _assert(&ptr->i == &array[0].i);
54 }
55 {
56 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
57 // ^ ^ ^
58 // | | |
59 // begin ptr end
60 test_bounded_ptr<QualT> ptr(array.begin() + 1, array.begin(), array.end());
61 QualT& ref = *ptr;
62 _assert(ref == T{1});
63 _assert(&ref == &array[1]);
64
65 _assert(ptr->i == 1);
66 _assert(&ptr->i == &array[1].i);
67 }
68 {
69 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
70 // ^ ^ ^
71 // | | |
72 // begin ptr end
73 test_bounded_ptr<QualT> ptr(array.begin() + 2, array.begin(), array.end());
74 QualT& ref = *ptr;
75 _assert(ref == T{2});
76 _assert(&ref == &array[2]);
77
78 _assert(ptr->i == 2);
79 _assert(&ptr->i == &array[2].i);
80 }
81 {
82 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
83 // ^ ^ ^
84 // | | |
85 // begin ptr end
86 test_bounded_ptr<QualT> ptr(array.begin() + 4, array.begin(), array.end());
87 QualT& ref = *ptr;
88 _assert(ref == T{4});
89 _assert(&ref == &array[4]);
90
91 _assert(ptr->i == 4);
92 _assert(&ptr->i == &array[4].i);
93 }
94
95 // Make sure we don't trap when dereferencing an in-bounds pointer
96 {
97 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
98 // ^ ^ ^
99 // | | |
100 // begin ptr end
101 libkern::bounded_ptr<QualT, tracking_policy> ptr(array.begin() + 1, array.begin(), array.end());
102
103 tracking_policy::did_trap = false;
104 (void)*ptr;
105 (void)ptr->i;
106 _assert(!tracking_policy::did_trap);
107 }
108
109 // Make sure we trap when dereferencing an out-of-bounds pointer
110 {
111 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
112 // ^ ^ ^
113 // | | |
114 // begin end ptr
115 libkern::bounded_ptr<QualT, tracking_policy> ptr(array.end() - 1, array.begin(), array.end() - 2);
116
117 tracking_policy::did_trap = false;
118 (void)*ptr;
119 _assert(tracking_policy::did_trap);
120
121 tracking_policy::did_trap = false;
122 (void)ptr->i;
123 _assert(tracking_policy::did_trap);
124 }
125 {
126 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
127 // ^ ^ ^
128 // | | |
129 // ptr begin end
130 libkern::bounded_ptr<QualT, tracking_policy> ptr(array.begin(), array.begin() + 1, array.end());
131
132 tracking_policy::did_trap = false;
133 (void)*ptr;
134 _assert(tracking_policy::did_trap);
135
136 tracking_policy::did_trap = false;
137 (void)ptr->i;
138 _assert(tracking_policy::did_trap);
139 }
140 {
141 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
142 // ^ ^ ^
143 // | (just a bit off) | |
144 // begin ptr end
145 T* t3 = const_cast<T*>(array.begin() + 3);
146 char* just_off = reinterpret_cast<char*>(t3) + 1; // 1 byte off
147 libkern::bounded_ptr<QualT, tracking_policy> ptr(reinterpret_cast<QualT*>(just_off), array.begin(), array.end() - 1);
148
149 tracking_policy::did_trap = false;
150 (void)*ptr;
151 _assert(tracking_policy::did_trap);
152
153 tracking_policy::did_trap = false;
154 (void)ptr->i;
155 _assert(tracking_policy::did_trap);
156 }
157 }
158
159 T_DECL(deref, "bounded_ptr.deref") {
160 tests<T, T>();
161 tests<T, T const>();
162 tests<T, T volatile>();
163 tests<T, T const volatile>();
164
165 // Make sure that we don't hard-error in the definition of operator*
166 // when instantiating a `bounded_ptr<cv-void>`
167 test_bounded_ptr<void> p1;
168 test_bounded_ptr<void const> p2;
169 test_bounded_ptr<void volatile> p3;
170 test_bounded_ptr<void const volatile> p4;
171 }