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