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