]>
git.saurik.com Git - apple/xnu.git/blob - tests/bounded_ptr_src/unsafe_discard_bounds.cpp
3 // T* unsafe_discard_bounds() const;
6 #include <libkern/c++/bounded_ptr.h>
11 #include <darwintest.h>
12 #include <darwintest_utils.h>
13 #include "test_utils.h"
15 #define _assert(...) T_ASSERT_TRUE((__VA_ARGS__), # __VA_ARGS__)
18 struct tracking_policy
{
26 bool tracking_policy::did_trap
= false;
31 template <typename T
, typename QualT
>
35 std::array
<T
, 5> array
= {T
{0}, T
{1}, T
{2}, T
{3}, T
{4}};
38 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
42 test_bounded_ptr
<QualT
> const ptr(array
.begin() + 0, array
.begin(), array
.end());
43 QualT
* raw
= ptr
.unsafe_discard_bounds();
44 _assert(raw
== &array
[0]);
47 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
51 test_bounded_ptr
<QualT
> const ptr(array
.begin() + 1, array
.begin(), array
.end());
52 QualT
* raw
= ptr
.unsafe_discard_bounds();
53 _assert(raw
== &array
[1]);
56 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
60 test_bounded_ptr
<QualT
> const ptr(array
.begin() + 2, array
.begin(), array
.end());
61 QualT
* raw
= ptr
.unsafe_discard_bounds();
62 _assert(raw
== &array
[2]);
65 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
69 test_bounded_ptr
<QualT
> const ptr(array
.begin() + 4, array
.begin(), array
.end());
70 QualT
* raw
= ptr
.unsafe_discard_bounds();
71 _assert(raw
== &array
[4]);
74 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
78 test_bounded_ptr
<QualT
> const ptr(array
.end(), array
.begin(), array
.end());
79 QualT
* raw
= ptr
.unsafe_discard_bounds();
80 _assert(raw
== array
.end());
83 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
87 test_bounded_ptr
<QualT
> ptr(array
.end() - 1, array
.begin(), array
.end() - 2);
88 QualT
* raw
= ptr
.unsafe_discard_bounds();
89 _assert(raw
== &array
[4]);
92 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
96 test_bounded_ptr
<QualT
> ptr(array
.begin() + 1, array
.begin(), array
.end());
97 QualT
* raw
= ptr
.unsafe_discard_bounds();
98 _assert(raw
== &array
[1]);
101 // T{0} T{1} T{2} T{3} T{4} <one-past-last>
105 test_bounded_ptr
<QualT
> ptr(array
.begin(), array
.begin() + 1, array
.end());
106 QualT
* raw
= ptr
.unsafe_discard_bounds();
107 _assert(raw
== &array
[0]);
110 // Test discarding the bounds of a null pointer
112 test_bounded_ptr
<QualT
> const ptr(nullptr, nullptr, nullptr);
113 QualT
* raw
= ptr
.unsafe_discard_bounds();
114 _assert(raw
== nullptr);
117 // Test discarding the bounds on a pointer outside of representable memory.
118 // Even `unsafe_discard_bounds()` will trap in such conditions.
120 // To do this, we setup an imaginary object with a very high address, and
121 // we add a large-ish offset to it, such that adding the base to the offset
122 // would fall outside of the representable memory.
124 tracking_policy::did_trap
= false;
126 QualT
* end_of_memory
= reinterpret_cast<QualT
*>(std::numeric_limits
<std::uintptr_t>::max());
127 QualT
* base
= end_of_memory
- 500; // yeah, technically UB
128 std::ptrdiff_t offset
= 501;
130 libkern::bounded_ptr
<QualT
, tracking_policy
> ptr(base
, base
, base
+ 1);
131 ptr
+= offset
; // now, `base_ + offset_` points outside of representable memory
133 _assert(!tracking_policy::did_trap
);
134 (void)ptr
.unsafe_discard_bounds();
135 _assert(tracking_policy::did_trap
);
139 T_DECL(unsafe_discard_bounds
, "bounded_ptr.unsafe_discard_bounds") {
142 tests
<T
, T
volatile>();
143 tests
<T
, T
const volatile>();