2 // IWYU pragma: private, include "rlbox.hpp"
3 // IWYU pragma: friend "rlbox_.*\.hpp"
9 #include "rlbox_conversion.hpp"
10 #include "rlbox_helpers.hpp"
11 #include "rlbox_types.hpp"
12 #include "rlbox_wrapper_traits.hpp"
14 namespace rlbox::detail
{
16 template<typename T
, typename T_Sbx
, typename T_Enable
= void>
17 struct convert_to_sandbox_equivalent_helper
;
19 template<typename T
, typename T_Sbx
>
20 struct convert_to_sandbox_equivalent_helper
<
23 std::enable_if_t
<!std::is_class_v
<T
>>>
25 using type
= typename rlbox_sandbox
<
26 T_Sbx
>::template convert_to_sandbox_equivalent_nonclass_t
<T
>;
29 template<typename T
, typename T_Sbx
>
30 using convert_to_sandbox_equivalent_t
=
31 typename convert_to_sandbox_equivalent_helper
<T
, T_Sbx
>::type
;
33 // This is used by rlbox_load_structs_from_library to test the current namespace
38 #define helper_create_converted_field(fieldType, fieldName, isFrozen) \
39 typename detail::convert_to_sandbox_equivalent_t<fieldType, T_Sbx> fieldName;
41 #define helper_no_op()
43 #define sandbox_equivalent_specialization(T, libId) \
44 template<typename T_Sbx> \
45 struct Sbx_##libId##_##T \
47 sandbox_fields_reflection_##libId##_class_##T( \
48 helper_create_converted_field, \
52 /* add convert_to_sandbox_equivalent_t specialization for new struct */ \
54 template<typename T_Template, typename T_Sbx> \
55 struct convert_to_sandbox_equivalent_helper< \
58 std::enable_if_t<std::is_same_v<T_Template, T>>> \
60 using type = Sbx_##libId##_##T<T_Sbx>; \
64 #define helper_create_tainted_field( \
65 fieldType, fieldName, isFrozen, MaybeConst) \
66 MaybeConst tainted<fieldType, T_Sbx> fieldName;
68 #define helper_create_tainted_vol_field( \
69 fieldType, fieldName, isFrozen, MaybeConst) \
70 MaybeConst tainted_volatile<fieldType, T_Sbx> fieldName;
72 #define helper_convert_type(fieldType, fieldName, isFrozen) \
73 ::rlbox::detail::convert_type<T_Sbx, Direction, Context>( \
74 lhs.fieldName, rhs.fieldName, example_unsandboxed_ptr, sandbox_ptr);
76 #define helper_find_example_pointer_or_null(fieldType, fieldName, isFrozen) \
78 const void* ret = fieldName.find_example_pointer_or_null(); \
79 if (ret != nullptr) { \
84 #define tainted_data_specialization_helper(MaybeConst, T, libId) \
86 template<typename T_Sbx> \
87 class tainted_volatile<MaybeConst T, T_Sbx> \
89 KEEP_CLASSES_FRIENDLY \
93 inline MaybeConst Sbx_##libId##_##T<T_Sbx>& \
94 get_sandbox_value_ref() noexcept \
96 return *reinterpret_cast<MaybeConst Sbx_##libId##_##T<T_Sbx>*>(this); \
99 inline const Sbx_##libId##_##T<T_Sbx>& get_sandbox_value_ref() \
102 return *reinterpret_cast<const Sbx_##libId##_##T<T_Sbx>*>(this); \
105 inline T get_raw_value() const noexcept \
108 const auto& rhs = get_sandbox_value_ref(); \
109 constexpr auto Direction = \
110 detail::adjust_type_direction::TO_APPLICATION; \
111 constexpr auto Context = detail::adjust_type_context::EXAMPLE; \
112 /* This is a tainted_volatile, so its address is a valid example for use \
113 * as example_unsandboxed_ptr */ \
114 const void* example_unsandboxed_ptr = &rhs; \
115 rlbox_sandbox<T_Sbx>* sandbox_ptr = nullptr; \
116 sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
122 /* get_raw_sandbox_value has to return a custom struct to deal with the \
123 * adjusted machine model, to ensure */ \
124 inline Sbx_##libId##_##T<T_Sbx> get_raw_sandbox_value() const noexcept \
126 auto ret_ptr = reinterpret_cast<const Sbx_##libId##_##T<T_Sbx>*>(this); \
130 tainted_volatile() = default; \
131 tainted_volatile(const tainted_volatile<MaybeConst T, T_Sbx>& p) = \
135 sandbox_fields_reflection_##libId##_class_##T( \
136 helper_create_tainted_vol_field, \
140 inline tainted<MaybeConst T*, T_Sbx> \
141 operator&() const noexcept \
144 reinterpret_cast<MaybeConst T*>(&get_sandbox_value_ref()); \
145 auto ret = tainted<MaybeConst T*, T_Sbx>::internal_factory(ref_cast); \
149 inline auto UNSAFE_unverified() const { return get_raw_value(); } \
150 inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) const \
152 return get_raw_sandbox_value(sandbox); \
156 inline auto unverified_safe_because(const char (&reason)[N]) const \
158 RLBOX_UNUSED(reason); \
159 return UNSAFE_unverified(); \
162 T copy_and_verify(std::function<T(tainted<T, T_Sbx>)> verifier) \
164 tainted<T, T_Sbx> val(*this); \
165 return verifier(val); \
168 /* Can't define this yet due, to mutually dependent definition between \
169 tainted and tainted_volatile for structs */ \
170 inline tainted_volatile<MaybeConst T, T_Sbx>& operator=( \
171 const tainted<T, T_Sbx>& rhs); \
174 template<typename T_Sbx> \
175 class tainted<MaybeConst T, T_Sbx> \
177 KEEP_CLASSES_FRIENDLY \
181 inline MaybeConst T& get_raw_value_ref() noexcept \
183 return *reinterpret_cast<MaybeConst T*>(this); \
186 inline const T& get_raw_value_ref() const noexcept \
188 return *reinterpret_cast<const T*>(this); \
191 inline T get_raw_value() const noexcept \
193 auto ret_ptr = reinterpret_cast<const T*>(this); \
197 /* get_raw_sandbox_value has to return a custom struct to deal with the \
198 * adjusted machine model, to ensure */ \
199 inline Sbx_##libId##_##T<T_Sbx> get_raw_sandbox_value( \
200 rlbox_sandbox<T_Sbx>& sandbox) const noexcept \
202 Sbx_##libId##_##T<T_Sbx> lhs; \
203 const auto& rhs = get_raw_value_ref(); \
204 constexpr auto Direction = detail::adjust_type_direction::TO_SANDBOX; \
205 constexpr auto Context = detail::adjust_type_context::SANDBOX; \
206 const void* example_unsandboxed_ptr = nullptr; \
207 rlbox_sandbox<T_Sbx>* sandbox_ptr = &sandbox; \
208 sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
214 inline const void* find_example_pointer_or_null() const noexcept \
216 sandbox_fields_reflection_##libId##_class_##T( \
217 helper_find_example_pointer_or_null, helper_no_op) \
223 sandbox_fields_reflection_##libId##_class_##T(helper_create_tainted_field, \
227 tainted() = default; \
228 tainted(const tainted<MaybeConst T, T_Sbx>& p) = default; \
230 tainted(const tainted_volatile<T, T_Sbx>& p) \
232 auto& lhs = get_raw_value_ref(); \
233 auto& rhs = p.get_sandbox_value_ref(); \
234 constexpr auto Direction = \
235 detail::adjust_type_direction::TO_APPLICATION; \
236 constexpr auto Context = detail::adjust_type_context::EXAMPLE; \
237 /* This is a tainted_volatile, so its address is a valid for use as */ \
238 /* example_unsandboxed_ptr */ \
239 const void* example_unsandboxed_ptr = &rhs; \
240 rlbox_sandbox<T_Sbx>* sandbox_ptr = nullptr; \
241 sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
245 inline tainted_opaque<MaybeConst T, T_Sbx> to_opaque() \
247 return *reinterpret_cast<tainted_opaque<MaybeConst T, T_Sbx>*>(this); \
250 inline auto UNSAFE_unverified() const { return get_raw_value(); } \
251 inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) const \
253 return get_raw_sandbox_value(sandbox); \
257 inline auto unverified_safe_because(const char (&reason)[N]) const \
259 RLBOX_UNUSED(reason); \
260 return UNSAFE_unverified(); \
263 T copy_and_verify(std::function<T(tainted<T, T_Sbx>)> verifier) \
265 return verifier(*this); \
269 /* Had to delay the definition due, to mutually dependence between \
270 tainted and tainted_volatile for structs */ \
271 template<typename T_Sbx> \
272 inline tainted_volatile<MaybeConst T, T_Sbx>& \
273 tainted_volatile<MaybeConst T, T_Sbx>::operator=( \
274 const tainted<T, T_Sbx>& rhs_wrap) \
276 auto& lhs = get_sandbox_value_ref(); \
277 auto& rhs = rhs_wrap.get_raw_value_ref(); \
278 constexpr auto Direction = detail::adjust_type_direction::TO_SANDBOX; \
279 constexpr auto Context = detail::adjust_type_context::EXAMPLE; \
280 /* This is a tainted_volatile, so its address is a valid example for */ \
281 /* use as example_unsandboxed_ptr */ \
282 const void* example_unsandboxed_ptr = &lhs; \
283 rlbox_sandbox<T_Sbx>* sandbox_ptr = nullptr; \
284 sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
290 #define tainted_data_specialization(T, libId) \
291 tainted_data_specialization_helper(, T, libId) \
292 tainted_data_specialization_helper(const, T, libId)
294 #define convert_type_specialization(T, libId) \
296 template<typename T_Sbx, \
297 detail::adjust_type_direction Direction, \
298 adjust_type_context Context, \
300 class convert_type_class<T_Sbx, Direction, Context, T, T_From> \
303 static inline void run(T& lhs, \
305 const void* example_unsandboxed_ptr, \
306 rlbox_sandbox<T_Sbx>* sandbox_ptr) \
308 sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
313 template<typename T_Sbx, \
314 detail::adjust_type_direction Direction, \
315 adjust_type_context Context, \
317 class convert_type_class<T_Sbx, \
320 Sbx_##libId##_##T<T_Sbx>, \
324 static inline void run(Sbx_##libId##_##T<T_Sbx>& lhs, \
326 const void* example_unsandboxed_ptr, \
327 rlbox_sandbox<T_Sbx>* sandbox_ptr) \
329 sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
336 #define rlbox_load_structs_from_library(libId) \
338 /* check that this macro is called in a global namespace */ \
340 ::rlbox::detail::is_member_of_rlbox_detail<detail::markerStruct>, \
341 "Invoke rlbox_load_structs_from_library in the global namespace"); \
343 sandbox_fields_reflection_##libId##_allClasses( \
344 sandbox_equivalent_specialization) \
346 sandbox_fields_reflection_##libId##_allClasses( \
347 tainted_data_specialization) \
349 sandbox_fields_reflection_##libId##_allClasses( \
350 convert_type_specialization) \
352 RLBOX_REQUIRE_SEMI_COLON