1 // 2 // Example of providing a malloc() wrapper that returns a `bounded_ptr`. 3 // 4 // This test serves as some kind of integration test, ensuring that we're 5 // able to convert existing code using raw pointers to using `bounded_ptr`s 6 // without too much hassle. This code was lifted from existing code in XNU, 7 // and the variable names were changed to make it more generic. 8 // 9 10 #include <libkern/c++/bounded_ptr.h> 11 #include <cstddef> 12 #include <cstdint> 13 #include <cstdlib> 14 #include <darwintest.h> 15 #include "test_utils.h" 16 17 test_bounded_ptr<void> 18 bounded_malloc(std::size_t size) 19 { 20 void* p = std::malloc(size); 21 void* end = static_cast<char*>(p) + size; 22 test_bounded_ptr<void> with_bounds(p, p, end); 23 return with_bounds; 24 } 25 26 void 27 bounded_free(test_bounded_ptr<void> ptr) 28 { 29 std::free(ptr.discard_bounds()); 30 } 31 32 struct SomeType { 33 std::uint32_t idx; 34 }; 35 36 // Pretend that those functions are already part of the code base being 37 // transitioned over to `bounded_ptr`s, and we can't change their signature. 38 // The purpose of having those functions is to make sure that we're able to 39 // integrate into existing code bases with decent ease. 40 void 41 use(SomeType*) 42 { 43 } 44 void 45 require(bool condition) 46 { 47 if (!condition) { 48 std::exit(EXIT_FAILURE); 49 } 50 } 51 52 T_DECL(example_malloc, "bounded_ptr.example.malloc") { 53 test_bounded_ptr<SomeType> array = nullptr; 54 std::uint32_t count = 100; 55 std::uint32_t alloc_size = count * sizeof(SomeType); 56 57 // (1) must use a bounded version of malloc 58 // (2) must use a reinterpret_pointer_cast to go from void* to SomeType* 59 array = libkern::reinterpret_pointer_cast<SomeType>(bounded_malloc(alloc_size)); 60 61 require(array != nullptr); // use != nullptr instead of relying on implicit conversion to bool 62 use(array.discard_bounds()); // must manually discard bounds here 63 64 for (std::uint32_t i = 0; i < count; i++) { 65 std::uint32_t& idx = array[i].idx; 66 idx = i; 67 use(&array[idx]); 68 } 69 70 if (array) { 71 bounded_free(array); // must use a bounded version of free 72 } 73 74 T_PASS("bounded_ptr.example.malloc test done"); 75 } 76