xref: /xnu-12377.41.6/tests/cxx_safe_buffers_src/reinterpret_span_cast.cpp (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1*bbb1b6f9SApple OSS Distributions /*
2*bbb1b6f9SApple OSS Distributions  * Tests for reinterpret_span_cast template in cxx_safe_buffers.h
3*bbb1b6f9SApple OSS Distributions  */
4*bbb1b6f9SApple OSS Distributions #include <os/cxx_safe_buffers.h>
5*bbb1b6f9SApple OSS Distributions #include <vector>
6*bbb1b6f9SApple OSS Distributions #include <darwintest.h>
7*bbb1b6f9SApple OSS Distributions #include <darwintest_utils.h>
8*bbb1b6f9SApple OSS Distributions #define CHECK(...) T_ASSERT_TRUE((__VA_ARGS__), # __VA_ARGS__)
9*bbb1b6f9SApple OSS Distributions 
10*bbb1b6f9SApple OSS Distributions struct A {
11*bbb1b6f9SApple OSS Distributions 	int a[2];
12*bbb1b6f9SApple OSS Distributions };
13*bbb1b6f9SApple OSS Distributions 
14*bbb1b6f9SApple OSS Distributions struct B {
15*bbb1b6f9SApple OSS Distributions 	int b[3];
16*bbb1b6f9SApple OSS Distributions };
17*bbb1b6f9SApple OSS Distributions 
18*bbb1b6f9SApple OSS Distributions struct C : B {
19*bbb1b6f9SApple OSS Distributions 	int c[3];
20*bbb1b6f9SApple OSS Distributions };
21*bbb1b6f9SApple OSS Distributions 
22*bbb1b6f9SApple OSS Distributions struct D {
23*bbb1b6f9SApple OSS Distributions 	std::uint8_t a[2];
24*bbb1b6f9SApple OSS Distributions };
25*bbb1b6f9SApple OSS Distributions 
26*bbb1b6f9SApple OSS Distributions struct NoPadding {
27*bbb1b6f9SApple OSS Distributions 	char a;
28*bbb1b6f9SApple OSS Distributions 	char b;
29*bbb1b6f9SApple OSS Distributions 
30*bbb1b6f9SApple OSS Distributions 	int c;
31*bbb1b6f9SApple OSS Distributions };
32*bbb1b6f9SApple OSS Distributions 
33*bbb1b6f9SApple OSS Distributions struct WithPaddingMiddle {
34*bbb1b6f9SApple OSS Distributions 	char a;
35*bbb1b6f9SApple OSS Distributions 	int b;
36*bbb1b6f9SApple OSS Distributions 
37*bbb1b6f9SApple OSS Distributions 	char c;
38*bbb1b6f9SApple OSS Distributions };
39*bbb1b6f9SApple OSS Distributions 
40*bbb1b6f9SApple OSS Distributions struct PaddingEnd {
41*bbb1b6f9SApple OSS Distributions 	int a;
42*bbb1b6f9SApple OSS Distributions 	char c;
43*bbb1b6f9SApple OSS Distributions };
44*bbb1b6f9SApple OSS Distributions 
45*bbb1b6f9SApple OSS Distributions 
46*bbb1b6f9SApple OSS Distributions static void
tests()47*bbb1b6f9SApple OSS Distributions tests()
48*bbb1b6f9SApple OSS Distributions {
49*bbb1b6f9SApple OSS Distributions 	{
50*bbb1b6f9SApple OSS Distributions 		// convert span<int> to span<byte>
51*bbb1b6f9SApple OSS Distributions 		std::array<int, 3> a1{{1, 2, 3}};
52*bbb1b6f9SApple OSS Distributions 		std::span<int> sp{a1}; // static-extent std::span
53*bbb1b6f9SApple OSS Distributions 		std::span<std::byte> writable_sp = os::reinterpret_span_cast<std::byte>(sp);
54*bbb1b6f9SApple OSS Distributions 		std::span<const std::byte> nonwritable_sp = os::reinterpret_span_cast<const std::byte>(sp);
55*bbb1b6f9SApple OSS Distributions 		CHECK(writable_sp.size() == sp.size_bytes() && nonwritable_sp.size() == sp.size_bytes());
56*bbb1b6f9SApple OSS Distributions 	}
57*bbb1b6f9SApple OSS Distributions 
58*bbb1b6f9SApple OSS Distributions 	{
59*bbb1b6f9SApple OSS Distributions 		// convert span<byte> to span<A>
60*bbb1b6f9SApple OSS Distributions 		std::vector<std::byte> vec {std::byte{0}, std::byte{1}, std::byte{2}, std::byte{3},
61*bbb1b6f9SApple OSS Distributions 			                    std::byte{4}, std::byte{5}, std::byte{6}, std::byte{7}};
62*bbb1b6f9SApple OSS Distributions 		std::span<std::byte> sp{vec}; // dynamic-extent std::span
63*bbb1b6f9SApple OSS Distributions 		std::span<A> span_a = os::reinterpret_span_cast<A>(sp);
64*bbb1b6f9SApple OSS Distributions 		CHECK(sp.size() == span_a.size_bytes());
65*bbb1b6f9SApple OSS Distributions 	}
66*bbb1b6f9SApple OSS Distributions 
67*bbb1b6f9SApple OSS Distributions 	{
68*bbb1b6f9SApple OSS Distributions 		// convert to a span of unrelated type
69*bbb1b6f9SApple OSS Distributions 		std::array<A, 3> arr;
70*bbb1b6f9SApple OSS Distributions 		std::span<A> span_a = arr;
71*bbb1b6f9SApple OSS Distributions 		std::span<B> span_b = os::reinterpret_span_cast<B>(span_a);
72*bbb1b6f9SApple OSS Distributions 		CHECK(span_b.size() == 2);
73*bbb1b6f9SApple OSS Distributions 	}
74*bbb1b6f9SApple OSS Distributions 
75*bbb1b6f9SApple OSS Distributions 	{
76*bbb1b6f9SApple OSS Distributions 		// convert to a span of extended type
77*bbb1b6f9SApple OSS Distributions 		B array[4];
78*bbb1b6f9SApple OSS Distributions 		std::span<B> span_b = array;
79*bbb1b6f9SApple OSS Distributions 		std::span<C> span_c = os::reinterpret_span_cast<C>(span_b);
80*bbb1b6f9SApple OSS Distributions 		CHECK(2 * span_c.size() == span_b.size());
81*bbb1b6f9SApple OSS Distributions 	}
82*bbb1b6f9SApple OSS Distributions 
83*bbb1b6f9SApple OSS Distributions 	{
84*bbb1b6f9SApple OSS Distributions 		//convert to a span of base type
85*bbb1b6f9SApple OSS Distributions 		C array[4];
86*bbb1b6f9SApple OSS Distributions 		std::span<C> span_c = array;
87*bbb1b6f9SApple OSS Distributions 		std::span<B> span_b = os::reinterpret_span_cast<B>(span_c);
88*bbb1b6f9SApple OSS Distributions 		CHECK(2 * span_c.size() == span_b.size());
89*bbb1b6f9SApple OSS Distributions 	}
90*bbb1b6f9SApple OSS Distributions 	{
91*bbb1b6f9SApple OSS Distributions 		std::array<std::uint8_t, 12> buf;
92*bbb1b6f9SApple OSS Distributions 		std::span<std::uint8_t> sp = buf;
93*bbb1b6f9SApple OSS Distributions 		std::span<D> span_d = os::reinterpret_span_cast<D>(sp);
94*bbb1b6f9SApple OSS Distributions 		CHECK(span_d.size() == 6);
95*bbb1b6f9SApple OSS Distributions 	}
96*bbb1b6f9SApple OSS Distributions }
97*bbb1b6f9SApple OSS Distributions 
98*bbb1b6f9SApple OSS Distributions static void
trapping_test()99*bbb1b6f9SApple OSS Distributions trapping_test()
100*bbb1b6f9SApple OSS Distributions {
101*bbb1b6f9SApple OSS Distributions 	pid_t pid = fork(); // Fork a new process
102*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(pid, "forked %d", pid);
103*bbb1b6f9SApple OSS Distributions 
104*bbb1b6f9SApple OSS Distributions 	if (pid == 0) {
105*bbb1b6f9SApple OSS Distributions 		// convert to a span of unrelated type
106*bbb1b6f9SApple OSS Distributions 		A array[2];
107*bbb1b6f9SApple OSS Distributions 		std::span<A> span_a = {array, 2};
108*bbb1b6f9SApple OSS Distributions 		// This invocation will cause a run time trap in child process.
109*bbb1b6f9SApple OSS Distributions 		std::span<B> span_b = os::reinterpret_span_cast<B>(span_a);
110*bbb1b6f9SApple OSS Distributions 
111*bbb1b6f9SApple OSS Distributions 		exit(0); // Exit child process
112*bbb1b6f9SApple OSS Distributions 	}
113*bbb1b6f9SApple OSS Distributions 
114*bbb1b6f9SApple OSS Distributions 	int status = 0, signal = 0;
115*bbb1b6f9SApple OSS Distributions 
116*bbb1b6f9SApple OSS Distributions 	// wait for the child process to finish
117*bbb1b6f9SApple OSS Distributions 	T_ASSERT_FALSE(dt_waitpid(pid, &status, &signal, 0), "wait for child (%d) complete with signal %d", pid, signal);
118*bbb1b6f9SApple OSS Distributions 	// child process must trigger an execution trap
119*bbb1b6f9SApple OSS Distributions 	T_ASSERT_TRUE(WIFSIGNALED(signal), "Child process successfully triggered an execution trap");
120*bbb1b6f9SApple OSS Distributions }
121*bbb1b6f9SApple OSS Distributions 
122*bbb1b6f9SApple OSS Distributions 
123*bbb1b6f9SApple OSS Distributions T_DECL(reinterpret_span_cast, "cxx_safe_buffers.reinterpret_span_cast")
124*bbb1b6f9SApple OSS Distributions {
125*bbb1b6f9SApple OSS Distributions 	tests();
126*bbb1b6f9SApple OSS Distributions 	trapping_test();
127*bbb1b6f9SApple OSS Distributions }
128