mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			354 lines
		
	
	
		
			No EOL
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			354 lines
		
	
	
		
			No EOL
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#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;
 | 
						|
 | 
						|
// This is used by rlbox_load_structs_from_library to test the current namespace
 | 
						|
struct markerStruct
 | 
						|
{};
 | 
						|
}
 | 
						|
 | 
						|
#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;                                                         \
 | 
						|
    }                                                                          \
 | 
						|
                                                                               \
 | 
						|
    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&() const 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() const { return get_raw_value(); }          \
 | 
						|
    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]) 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 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() const { return get_raw_value(); }          \
 | 
						|
    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]) 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 {                                                            \
 | 
						|
    /* 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
 |