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