summaryrefslogtreecommitdiffstats
path: root/third_party/rlbox/include/rlbox_struct_support.hpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rlbox/include/rlbox_struct_support.hpp
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rlbox/include/rlbox_struct_support.hpp')
-rw-r--r--third_party/rlbox/include/rlbox_struct_support.hpp403
1 files changed, 403 insertions, 0 deletions
diff --git a/third_party/rlbox/include/rlbox_struct_support.hpp b/third_party/rlbox/include/rlbox_struct_support.hpp
new file mode 100644
index 0000000000..f397cdda97
--- /dev/null
+++ b/third_party/rlbox/include/rlbox_struct_support.hpp
@@ -0,0 +1,403 @@
+#pragma once
+// IWYU pragma: private, include "rlbox.hpp"
+// IWYU pragma: friend "rlbox_.*\.hpp"
+
+#include <cstring>
+#include <functional>
+#include <type_traits>
+
+#include "rlbox_conversion.hpp"
+#include "rlbox_helpers.hpp"
+#include "rlbox_types.hpp"
+#include "rlbox_wrapper_traits.hpp"
+
+namespace rlbox::detail {
+
+template<typename T, typename T_Sbx, typename T_Enable = void>
+struct convert_to_sandbox_equivalent_helper;
+
+template<typename T, typename T_Sbx>
+struct convert_to_sandbox_equivalent_helper<
+ T,
+ T_Sbx,
+ std::enable_if_t<!std::is_class_v<T>>>
+{
+ using type = typename rlbox_sandbox<
+ T_Sbx>::template convert_to_sandbox_equivalent_nonclass_t<T>;
+};
+
+template<typename T, typename T_Sbx>
+using convert_to_sandbox_equivalent_t =
+ typename convert_to_sandbox_equivalent_helper<T, T_Sbx>::type;
+
+}
+
+#define helper_create_converted_field(fieldType, fieldName, isFrozen) \
+ typename detail::convert_to_sandbox_equivalent_t<fieldType, T_Sbx> fieldName;
+
+#define helper_no_op()
+
+#define sandbox_equivalent_specialization(T, libId) \
+ template<typename T_Sbx> \
+ struct Sbx_##libId##_##T \
+ { \
+ sandbox_fields_reflection_##libId##_class_##T( \
+ helper_create_converted_field, \
+ helper_no_op) \
+ }; \
+ \
+ /* add convert_to_sandbox_equivalent_t specialization for new struct */ \
+ namespace detail { \
+ template<typename T_Template, typename T_Sbx> \
+ struct convert_to_sandbox_equivalent_helper< \
+ T_Template, \
+ T_Sbx, \
+ std::enable_if_t<std::is_same_v<T_Template, T>>> \
+ { \
+ using type = Sbx_##libId##_##T<T_Sbx>; \
+ }; \
+ }
+
+#define helper_create_tainted_field( \
+ fieldType, fieldName, isFrozen, MaybeConst) \
+ MaybeConst tainted<fieldType, T_Sbx> fieldName;
+
+#define helper_create_tainted_vol_field( \
+ fieldType, fieldName, isFrozen, MaybeConst) \
+ MaybeConst tainted_volatile<fieldType, T_Sbx> fieldName;
+
+#define helper_convert_type(fieldType, fieldName, isFrozen) \
+ ::rlbox::detail::convert_type<T_Sbx, Direction, Context>( \
+ lhs.fieldName, rhs.fieldName, example_unsandboxed_ptr, sandbox_ptr);
+
+#define helper_find_example_pointer_or_null(fieldType, fieldName, isFrozen) \
+ { \
+ const void* ret = fieldName.find_example_pointer_or_null(); \
+ if (ret != nullptr) { \
+ return ret; \
+ } \
+ }
+
+#define tainted_data_specialization_helper(MaybeConst, T, libId) \
+ \
+ template<typename T_Sbx> \
+ class tainted_volatile<MaybeConst T, T_Sbx> \
+ { \
+ KEEP_CLASSES_FRIENDLY \
+ KEEP_CAST_FRIENDLY \
+ \
+ private: \
+ inline MaybeConst Sbx_##libId##_##T<T_Sbx>& \
+ get_sandbox_value_ref() noexcept \
+ { \
+ return *reinterpret_cast<MaybeConst Sbx_##libId##_##T<T_Sbx>*>(this); \
+ } \
+ \
+ inline const Sbx_##libId##_##T<T_Sbx>& get_sandbox_value_ref() \
+ const noexcept \
+ { \
+ return *reinterpret_cast<const Sbx_##libId##_##T<T_Sbx>*>(this); \
+ } \
+ \
+ inline T get_raw_value() const noexcept \
+ { \
+ T lhs; \
+ const auto& rhs = get_sandbox_value_ref(); \
+ constexpr auto Direction = \
+ detail::adjust_type_direction::TO_APPLICATION; \
+ constexpr auto Context = detail::adjust_type_context::EXAMPLE; \
+ /* This is a tainted_volatile, so its address is a valid example for use \
+ * as example_unsandboxed_ptr */ \
+ const void* example_unsandboxed_ptr = &rhs; \
+ rlbox_sandbox<T_Sbx>* sandbox_ptr = nullptr; \
+ sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
+ helper_no_op) \
+ \
+ return lhs; \
+ } \
+ \
+ /* get_raw_sandbox_value has to return a custom struct to deal with the \
+ * adjusted machine model, to ensure */ \
+ inline Sbx_##libId##_##T<T_Sbx> get_raw_sandbox_value() const noexcept \
+ { \
+ auto ret_ptr = reinterpret_cast<const Sbx_##libId##_##T<T_Sbx>*>(this); \
+ return *ret_ptr; \
+ } \
+ \
+ inline std::remove_cv_t<T> get_raw_value() noexcept \
+ { \
+ rlbox_detail_forward_to_const(get_raw_value, std::remove_cv_t<T>); \
+ } \
+ \
+ inline std::remove_cv_t<Sbx_##libId##_##T<T_Sbx>> \
+ get_raw_sandbox_value() noexcept \
+ { \
+ rlbox_detail_forward_to_const( \
+ get_raw_sandbox_value, std::remove_cv_t<Sbx_##libId##_##T<T_Sbx>>); \
+ } \
+ \
+ tainted_volatile() = default; \
+ tainted_volatile(const tainted_volatile<MaybeConst T, T_Sbx>& p) = \
+ default; \
+ \
+ public: \
+ sandbox_fields_reflection_##libId##_class_##T( \
+ helper_create_tainted_vol_field, \
+ helper_no_op, \
+ MaybeConst) \
+ \
+ inline tainted<MaybeConst T*, T_Sbx> \
+ operator&() noexcept \
+ { \
+ auto ref_cast = \
+ reinterpret_cast<MaybeConst T*>(&get_sandbox_value_ref()); \
+ auto ret = tainted<MaybeConst T*, T_Sbx>::internal_factory(ref_cast); \
+ return ret; \
+ } \
+ \
+ inline auto UNSAFE_unverified() { return get_raw_value(); } \
+ inline auto UNSAFE_unverified() const { return get_raw_value(); } \
+ inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) \
+ { \
+ return get_raw_sandbox_value(sandbox); \
+ } \
+ inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) const \
+ { \
+ return get_raw_sandbox_value(sandbox); \
+ } \
+ \
+ template<size_t N> \
+ inline auto unverified_safe_because(const char (&reason)[N]) \
+ { \
+ RLBOX_UNUSED(reason); \
+ return UNSAFE_unverified(); \
+ } \
+ template<size_t N> \
+ inline auto unverified_safe_because(const char (&reason)[N]) const \
+ { \
+ RLBOX_UNUSED(reason); \
+ return UNSAFE_unverified(); \
+ } \
+ \
+ T copy_and_verify(std::function<T(tainted<T, T_Sbx>)> verifier) \
+ { \
+ tainted<T, T_Sbx> val(*this); \
+ return verifier(val); \
+ } \
+ \
+ /* Can't define this yet due, to mutually dependent definition between \
+ tainted and tainted_volatile for structs */ \
+ inline tainted_volatile<MaybeConst T, T_Sbx>& operator=( \
+ const tainted<T, T_Sbx>& rhs); \
+ }; \
+ \
+ template<typename T_Sbx> \
+ class tainted<MaybeConst T, T_Sbx> \
+ { \
+ KEEP_CLASSES_FRIENDLY \
+ KEEP_CAST_FRIENDLY \
+ \
+ private: \
+ inline MaybeConst T& get_raw_value_ref() noexcept \
+ { \
+ return *reinterpret_cast<MaybeConst T*>(this); \
+ } \
+ \
+ inline const T& get_raw_value_ref() const noexcept \
+ { \
+ return *reinterpret_cast<const T*>(this); \
+ } \
+ \
+ inline T get_raw_value() const noexcept \
+ { \
+ auto ret_ptr = reinterpret_cast<const T*>(this); \
+ return *ret_ptr; \
+ } \
+ \
+ /* get_raw_sandbox_value has to return a custom struct to deal with the \
+ * adjusted machine model, to ensure */ \
+ inline Sbx_##libId##_##T<T_Sbx> get_raw_sandbox_value( \
+ rlbox_sandbox<T_Sbx>& sandbox) const noexcept \
+ { \
+ Sbx_##libId##_##T<T_Sbx> lhs; \
+ const auto& rhs = get_raw_value_ref(); \
+ constexpr auto Direction = detail::adjust_type_direction::TO_SANDBOX; \
+ constexpr auto Context = detail::adjust_type_context::SANDBOX; \
+ const void* example_unsandboxed_ptr = nullptr; \
+ rlbox_sandbox<T_Sbx>* sandbox_ptr = &sandbox; \
+ sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
+ helper_no_op) \
+ \
+ return lhs; \
+ } \
+ \
+ inline std::remove_cv_t<T> get_raw_value() noexcept \
+ { \
+ rlbox_detail_forward_to_const(get_raw_value, std::remove_cv_t<T>); \
+ } \
+ \
+ inline std::remove_cv_t<Sbx_##libId##_##T<T_Sbx>> get_raw_sandbox_value( \
+ rlbox_sandbox<T_Sbx>& sandbox) noexcept \
+ { \
+ rlbox_detail_forward_to_const_a( \
+ get_raw_sandbox_value, \
+ std::remove_cv_t<Sbx_##libId##_##T<T_Sbx>>, \
+ sandbox); \
+ } \
+ \
+ inline const void* find_example_pointer_or_null() const noexcept \
+ { \
+ sandbox_fields_reflection_##libId##_class_##T( \
+ helper_find_example_pointer_or_null, helper_no_op) \
+ \
+ return nullptr; \
+ } \
+ \
+ public: \
+ sandbox_fields_reflection_##libId##_class_##T(helper_create_tainted_field, \
+ helper_no_op, \
+ MaybeConst) \
+ \
+ tainted() = default; \
+ tainted(const tainted<MaybeConst T, T_Sbx>& p) = default; \
+ \
+ tainted(const tainted_volatile<T, T_Sbx>& p) \
+ { \
+ auto& lhs = get_raw_value_ref(); \
+ auto& rhs = p.get_sandbox_value_ref(); \
+ constexpr auto Direction = \
+ detail::adjust_type_direction::TO_APPLICATION; \
+ constexpr auto Context = detail::adjust_type_context::EXAMPLE; \
+ /* This is a tainted_volatile, so its address is a valid for use as */ \
+ /* example_unsandboxed_ptr */ \
+ const void* example_unsandboxed_ptr = &rhs; \
+ rlbox_sandbox<T_Sbx>* sandbox_ptr = nullptr; \
+ sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
+ helper_no_op) \
+ } \
+ \
+ inline tainted_opaque<MaybeConst T, T_Sbx> to_opaque() \
+ { \
+ return *reinterpret_cast<tainted_opaque<MaybeConst T, T_Sbx>*>(this); \
+ } \
+ \
+ inline auto UNSAFE_unverified() { return get_raw_value(); } \
+ inline auto UNSAFE_unverified() const { return get_raw_value(); } \
+ inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) \
+ { \
+ return get_raw_sandbox_value(sandbox); \
+ } \
+ inline auto UNSAFE_sandboxed(rlbox_sandbox<T_Sbx>& sandbox) const \
+ { \
+ return get_raw_sandbox_value(sandbox); \
+ } \
+ \
+ template<size_t N> \
+ inline auto unverified_safe_because(const char (&reason)[N]) \
+ { \
+ RLBOX_UNUSED(reason); \
+ return UNSAFE_unverified(); \
+ } \
+ template<size_t N> \
+ inline auto unverified_safe_because(const char (&reason)[N]) const \
+ { \
+ RLBOX_UNUSED(reason); \
+ return UNSAFE_unverified(); \
+ } \
+ \
+ T copy_and_verify(std::function<T(tainted<T, T_Sbx>)> verifier) \
+ { \
+ return verifier(*this); \
+ } \
+ }; \
+ \
+ /* Had to delay the definition due, to mutually dependence between \
+ tainted and tainted_volatile for structs */ \
+ template<typename T_Sbx> \
+ inline tainted_volatile<MaybeConst T, T_Sbx>& \
+ tainted_volatile<MaybeConst T, T_Sbx>::operator=( \
+ const tainted<T, T_Sbx>& rhs_wrap) \
+ { \
+ auto& lhs = get_sandbox_value_ref(); \
+ auto& rhs = rhs_wrap.get_raw_value_ref(); \
+ constexpr auto Direction = detail::adjust_type_direction::TO_SANDBOX; \
+ constexpr auto Context = detail::adjust_type_context::EXAMPLE; \
+ /* This is a tainted_volatile, so its address is a valid example for */ \
+ /* use as example_unsandboxed_ptr */ \
+ const void* example_unsandboxed_ptr = &lhs; \
+ rlbox_sandbox<T_Sbx>* sandbox_ptr = nullptr; \
+ sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
+ helper_no_op) \
+ \
+ return *this; \
+ }
+
+#define tainted_data_specialization(T, libId) \
+ tainted_data_specialization_helper(, T, libId) \
+ tainted_data_specialization_helper(const, T, libId)
+
+#define convert_type_specialization(T, libId) \
+ namespace detail { \
+ template<typename T_Sbx, \
+ detail::adjust_type_direction Direction, \
+ adjust_type_context Context, \
+ typename T_From> \
+ class convert_type_class<T_Sbx, Direction, Context, T, T_From> \
+ { \
+ public: \
+ static inline void run(T& lhs, \
+ const T_From& rhs, \
+ const void* example_unsandboxed_ptr, \
+ rlbox_sandbox<T_Sbx>* sandbox_ptr) \
+ { \
+ sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
+ helper_no_op) \
+ } \
+ }; \
+ \
+ template<typename T_Sbx, \
+ detail::adjust_type_direction Direction, \
+ adjust_type_context Context, \
+ typename T_From> \
+ class convert_type_class<T_Sbx, \
+ Direction, \
+ Context, \
+ Sbx_##libId##_##T<T_Sbx>, \
+ T_From> \
+ { \
+ public: \
+ static inline void run(Sbx_##libId##_##T<T_Sbx>& lhs, \
+ const T_From& rhs, \
+ const void* example_unsandboxed_ptr, \
+ rlbox_sandbox<T_Sbx>* sandbox_ptr) \
+ { \
+ sandbox_fields_reflection_##libId##_class_##T(helper_convert_type, \
+ helper_no_op) \
+ } \
+ }; \
+ }
+
+// clang-format off
+#define rlbox_load_structs_from_library(libId) \
+ namespace rlbox { \
+ namespace detail { \
+ struct markerStruct \
+ {}; \
+ } \
+ /* check that this macro is called in a global namespace */ \
+ static_assert( \
+ ::rlbox::detail::is_member_of_rlbox_detail<detail::markerStruct>, \
+ "Invoke rlbox_load_structs_from_library in the global namespace"); \
+ \
+ sandbox_fields_reflection_##libId##_allClasses( \
+ sandbox_equivalent_specialization) \
+ \
+ sandbox_fields_reflection_##libId##_allClasses( \
+ tainted_data_specialization) \
+ \
+ sandbox_fields_reflection_##libId##_allClasses( \
+ convert_type_specialization) \
+ } \
+ RLBOX_REQUIRE_SEMI_COLON
+
+// clang-format on \ No newline at end of file