1 //
2 // Tests for
3 //  T& operator[](std::ptrdiff_t n);
4 //  T const& operator[](std::ptrdiff_t n) const;
5 //
6 
7 #include <libkern/c++/safe_allocation.h>
8 #include <darwintest.h>
9 #include "test_utils.h"
10 #include <cstddef>
11 #include <limits>
12 
13 struct T {
14 	long i;
15 };
16 
17 template <typename RawT, typename QualT>
18 static void
tests()19 tests()
20 {
21 	// Test the non-const version
22 	{
23 		RawT* memory = reinterpret_cast<RawT*>(malloc_allocator::allocate(10 * sizeof(RawT)));
24 		for (RawT* ptr = memory; ptr != memory + 10; ++ptr) {
25 			*ptr = RawT{ptr - memory}; // number from 0 to 9
26 		}
27 
28 		test_safe_allocation<QualT> array(memory, 10, libkern::adopt_memory);
29 		for (std::ptrdiff_t n = 0; n != 10; ++n) {
30 			QualT& element = array[n];
31 			CHECK(&element == memory + n);
32 		}
33 	}
34 
35 	// Test the const version
36 	{
37 		RawT* memory = reinterpret_cast<RawT*>(malloc_allocator::allocate(10 * sizeof(RawT)));
38 		for (RawT* ptr = memory; ptr != memory + 10; ++ptr) {
39 			*ptr = RawT{ptr - memory}; // number from 0 to 9
40 		}
41 
42 		test_safe_allocation<QualT> const array(memory, 10, libkern::adopt_memory);
43 		for (std::ptrdiff_t n = 0; n != 10; ++n) {
44 			QualT const& element = array[n];
45 			CHECK(&element == memory + n);
46 		}
47 	}
48 
49 	// Test with OOB offsets (should trap)
50 	{
51 		using Alloc = libkern::safe_allocation<RawT, malloc_allocator, tracking_trapping_policy>;
52 		RawT* memory = reinterpret_cast<RawT*>(malloc_allocator::allocate(10 * sizeof(RawT)));
53 		Alloc const array(memory, 10, libkern::adopt_memory);
54 
55 		// Negative offsets
56 		{
57 			tracking_trapping_policy::reset();
58 			(void)array[-1];
59 			CHECK(tracking_trapping_policy::did_trap);
60 		}
61 		{
62 			tracking_trapping_policy::reset();
63 			(void)array[-10];
64 			CHECK(tracking_trapping_policy::did_trap);
65 		}
66 
67 		// Too large offsets
68 		{
69 			tracking_trapping_policy::reset();
70 			(void)array[10];
71 			CHECK(tracking_trapping_policy::did_trap);
72 		}
73 		{
74 			tracking_trapping_policy::reset();
75 			(void)array[11];
76 			CHECK(tracking_trapping_policy::did_trap);
77 		}
78 	}
79 }
80 
81 T_DECL(operator_subscript, "safe_allocation.operator.subscript", T_META_TAG_VM_PREFERRED) {
82 	tests<T, T>();
83 	tests<T, T const>();
84 }
85