ValueWithShadow.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Format.h>
  8. #include <AK/Platform.h>
  9. #include <AK/UFixedBigInt.h>
  10. #include <string.h>
  11. namespace UserspaceEmulator {
  12. constexpr u64 _initialized_64 = 0x01010101'01010101LLU;
  13. constexpr u128 _initialized_128 = u128(_initialized_64, _initialized_64);
  14. constexpr u256 _initialized_256 = u256(_initialized_128, _initialized_128);
  15. template<typename T>
  16. class ValueAndShadowReference;
  17. template<typename T>
  18. class ValueWithShadow {
  19. public:
  20. using ValueType = T;
  21. ValueWithShadow(T value, T shadow)
  22. : m_value(value)
  23. , m_shadow(shadow)
  24. {
  25. }
  26. ValueWithShadow(const ValueAndShadowReference<T>&);
  27. T value() const { return m_value; }
  28. T shadow() const { return m_shadow; }
  29. bool is_uninitialized() const
  30. {
  31. if constexpr (sizeof(T) == 32)
  32. return (m_shadow & _initialized_256) != _initialized_256;
  33. if constexpr (sizeof(T) == 16)
  34. return (m_shadow & _initialized_128) != _initialized_128;
  35. if constexpr (sizeof(T) == 8)
  36. return (m_shadow & _initialized_64) != _initialized_64;
  37. if constexpr (sizeof(T) == 4)
  38. return (m_shadow & 0x01010101) != 0x01010101;
  39. if constexpr (sizeof(T) == 2)
  40. return (m_shadow & 0x0101) != 0x0101;
  41. if constexpr (sizeof(T) == 1)
  42. return (m_shadow & 0x01) != 0x01;
  43. }
  44. void set_initialized()
  45. {
  46. if constexpr (sizeof(T) == 32)
  47. m_shadow = _initialized_256;
  48. if constexpr (sizeof(T) == 16)
  49. m_shadow = _initialized_128;
  50. if constexpr (sizeof(T) == 8)
  51. m_shadow = _initialized_64;
  52. if constexpr (sizeof(T) == 4)
  53. m_shadow = 0x01010101;
  54. if constexpr (sizeof(T) == 2)
  55. m_shadow = 0x0101;
  56. if constexpr (sizeof(T) == 1)
  57. m_shadow = 0x01;
  58. }
  59. private:
  60. T m_value;
  61. T m_shadow;
  62. };
  63. template<typename T>
  64. class ValueAndShadowReference {
  65. public:
  66. using ValueType = T;
  67. ValueAndShadowReference(T& value, T& shadow)
  68. : m_value(value)
  69. , m_shadow(shadow)
  70. {
  71. }
  72. bool is_uninitialized() const
  73. {
  74. if constexpr (sizeof(T) == 32)
  75. return (m_shadow & _initialized_256) != _initialized_256;
  76. if constexpr (sizeof(T) == 16)
  77. return (m_shadow & _initialized_128) != _initialized_128;
  78. if constexpr (sizeof(T) == 8)
  79. return (m_shadow & _initialized_64) != _initialized_64;
  80. if constexpr (sizeof(T) == 4)
  81. return (m_shadow & 0x01010101) != 0x01010101;
  82. if constexpr (sizeof(T) == 2)
  83. return (m_shadow & 0x0101) != 0x0101;
  84. if constexpr (sizeof(T) == 1)
  85. return (m_shadow & 0x01) != 0x01;
  86. }
  87. ValueAndShadowReference<T>& operator=(const ValueWithShadow<T>&);
  88. T& value() { return m_value; }
  89. T& shadow() { return m_shadow; }
  90. const T& value() const { return m_value; }
  91. const T& shadow() const { return m_shadow; }
  92. private:
  93. T& m_value;
  94. T& m_shadow;
  95. };
  96. template<typename T>
  97. ALWAYS_INLINE ValueWithShadow<T> shadow_wrap_as_initialized(T value)
  98. {
  99. if constexpr (sizeof(T) == 32)
  100. return { value, _initialized_256 };
  101. if constexpr (sizeof(T) == 16)
  102. return { value, _initialized_128 };
  103. if constexpr (sizeof(T) == 8)
  104. return { value, _initialized_64 };
  105. if constexpr (sizeof(T) == 4)
  106. return { value, 0x01010101 };
  107. if constexpr (sizeof(T) == 2)
  108. return { value, 0x0101 };
  109. if constexpr (sizeof(T) == 1)
  110. return { value, 0x01 };
  111. }
  112. template<typename T, typename U>
  113. ALWAYS_INLINE ValueWithShadow<T> shadow_wrap_with_taint_from(T value, const U& taint_a)
  114. {
  115. if (taint_a.is_uninitialized())
  116. return { value, 0 };
  117. return shadow_wrap_as_initialized(value);
  118. }
  119. template<typename T, typename U, typename V>
  120. ALWAYS_INLINE ValueWithShadow<T> shadow_wrap_with_taint_from(T value, const U& taint_a, const V& taint_b)
  121. {
  122. if (taint_a.is_uninitialized() || taint_b.is_uninitialized())
  123. return { value, 0 };
  124. return shadow_wrap_as_initialized(value);
  125. }
  126. template<typename T, typename U, typename V, typename X>
  127. ALWAYS_INLINE ValueWithShadow<T> shadow_wrap_with_taint_from(T value, const U& taint_a, const V& taint_b, const X& taint_c)
  128. {
  129. if (taint_a.is_uninitialized() || taint_b.is_uninitialized() || taint_c.is_uninitialized())
  130. return { value, 0 };
  131. return shadow_wrap_as_initialized(value);
  132. }
  133. template<typename T>
  134. inline ValueWithShadow<T>::ValueWithShadow(const ValueAndShadowReference<T>& other)
  135. : m_value(other.value())
  136. , m_shadow(other.shadow())
  137. {
  138. }
  139. template<typename T>
  140. inline ValueAndShadowReference<T>& ValueAndShadowReference<T>::operator=(const ValueWithShadow<T>& other)
  141. {
  142. m_value = other.value();
  143. m_shadow = other.shadow();
  144. return *this;
  145. }
  146. }
  147. template<typename T>
  148. struct AK::Formatter<UserspaceEmulator::ValueWithShadow<T>> : AK::Formatter<T> {
  149. ErrorOr<void> format(FormatBuilder& builder, UserspaceEmulator::ValueWithShadow<T> value)
  150. {
  151. return Formatter<T>::format(builder, value.value());
  152. }
  153. };
  154. #undef INITIALIZED_64
  155. #undef INITIALIZED_128
  156. #undef INITIALIZED_256