Validator.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/HashTable.h>
  8. #include <LibWasm/Forward.h>
  9. #include <LibWasm/Types.h>
  10. #if WASM_VALIDATOR_DEBUG
  11. # include <AK/SourceLocation.h>
  12. #endif
  13. namespace Wasm {
  14. struct Context {
  15. Vector<FunctionType> types;
  16. Vector<FunctionType> functions;
  17. Vector<TableType> tables;
  18. Vector<MemoryType> memories;
  19. Vector<GlobalType> globals;
  20. Vector<ValueType> elements;
  21. Vector<bool> datas;
  22. Vector<ValueType> locals;
  23. Vector<ResultType> labels;
  24. Optional<ResultType> return_;
  25. AK::HashTable<FunctionIndex> references;
  26. size_t imported_function_count { 0 };
  27. };
  28. struct ValidationError : public Error {
  29. ValidationError(String error)
  30. : Error(Error::from_string_literal(error))
  31. , error_string(move(error))
  32. {
  33. }
  34. String error_string;
  35. };
  36. class Validator {
  37. AK_MAKE_NONCOPYABLE(Validator);
  38. AK_MAKE_NONMOVABLE(Validator);
  39. public:
  40. Validator() = default;
  41. [[nodiscard]] Validator fork() const
  42. {
  43. return Validator { m_context };
  44. }
  45. // Module
  46. ErrorOr<void, ValidationError> validate(Module&);
  47. ErrorOr<void, ValidationError> validate(ImportSection const&);
  48. ErrorOr<void, ValidationError> validate(ExportSection const&);
  49. ErrorOr<void, ValidationError> validate(StartSection const&);
  50. ErrorOr<void, ValidationError> validate(DataSection const&);
  51. ErrorOr<void, ValidationError> validate(ElementSection const&);
  52. ErrorOr<void, ValidationError> validate(GlobalSection const&);
  53. ErrorOr<void, ValidationError> validate(MemorySection const&);
  54. ErrorOr<void, ValidationError> validate(TableSection const&);
  55. ErrorOr<void, ValidationError> validate(CodeSection const&);
  56. ErrorOr<void, ValidationError> validate(FunctionSection const&) { return {}; }
  57. ErrorOr<void, ValidationError> validate(DataCountSection const&) { return {}; }
  58. ErrorOr<void, ValidationError> validate(TypeSection const&) { return {}; }
  59. ErrorOr<void, ValidationError> validate(CustomSection const&) { return {}; }
  60. ErrorOr<void, ValidationError> validate(TypeIndex index) const
  61. {
  62. if (index.value() < m_context.types.size())
  63. return {};
  64. return Errors::invalid("TypeIndex"sv);
  65. }
  66. ErrorOr<void, ValidationError> validate(FunctionIndex index) const
  67. {
  68. if (index.value() < m_context.functions.size())
  69. return {};
  70. return Errors::invalid("FunctionIndex"sv);
  71. }
  72. ErrorOr<void, ValidationError> validate(MemoryIndex index) const
  73. {
  74. if (index.value() < m_context.memories.size())
  75. return {};
  76. return Errors::invalid("MemoryIndex"sv);
  77. }
  78. ErrorOr<void, ValidationError> validate(ElementIndex index) const
  79. {
  80. if (index.value() < m_context.elements.size())
  81. return {};
  82. return Errors::invalid("ElementIndex"sv);
  83. }
  84. ErrorOr<void, ValidationError> validate(DataIndex index) const
  85. {
  86. if (index.value() < m_context.datas.size())
  87. return {};
  88. return Errors::invalid("DataIndex"sv);
  89. }
  90. ErrorOr<void, ValidationError> validate(GlobalIndex index) const
  91. {
  92. if (index.value() < m_context.globals.size())
  93. return {};
  94. return Errors::invalid("GlobalIndex"sv);
  95. }
  96. ErrorOr<void, ValidationError> validate(LabelIndex index) const
  97. {
  98. if (index.value() < m_context.labels.size())
  99. return {};
  100. return Errors::invalid("LabelIndex"sv);
  101. }
  102. ErrorOr<void, ValidationError> validate(LocalIndex index) const
  103. {
  104. if (index.value() < m_context.locals.size())
  105. return {};
  106. return Errors::invalid("LocalIndex"sv);
  107. }
  108. ErrorOr<void, ValidationError> validate(TableIndex index) const
  109. {
  110. if (index.value() < m_context.tables.size())
  111. return {};
  112. return Errors::invalid("TableIndex"sv);
  113. }
  114. // Instructions
  115. struct StackEntry {
  116. StackEntry(ValueType type)
  117. : concrete_type(type)
  118. , is_known(true)
  119. {
  120. }
  121. explicit StackEntry()
  122. : concrete_type(ValueType::I32)
  123. , is_known(false)
  124. {
  125. }
  126. bool is_of_kind(ValueType::Kind kind) const
  127. {
  128. if (is_known)
  129. return concrete_type.kind() == kind;
  130. return true;
  131. }
  132. bool is_numeric() const { return !is_known || concrete_type.is_numeric(); }
  133. bool is_reference() const { return !is_known || concrete_type.is_reference(); }
  134. bool operator==(ValueType const& other) const
  135. {
  136. if (is_known)
  137. return concrete_type == other;
  138. return true;
  139. }
  140. bool operator==(StackEntry const& other) const
  141. {
  142. if (is_known && other.is_known)
  143. return other.concrete_type == concrete_type;
  144. return true;
  145. }
  146. ValueType concrete_type;
  147. bool is_known { true };
  148. };
  149. // This is a wrapper that can model "polymorphic" stacks,
  150. // by treating unknown stack entries as a potentially infinite number of entries
  151. class Stack : private Vector<StackEntry> {
  152. public:
  153. // The unknown entry will never be popped off, so we can safely use the original `is_empty`.
  154. using Vector<StackEntry>::is_empty;
  155. using Vector<StackEntry>::last;
  156. using Vector<StackEntry>::at;
  157. StackEntry take_last()
  158. {
  159. if (last().is_known)
  160. return Vector<StackEntry>::take_last();
  161. return last();
  162. }
  163. void append(StackEntry entry)
  164. {
  165. if (!entry.is_known)
  166. m_did_insert_unknown_entry = true;
  167. Vector<StackEntry>::append(entry);
  168. }
  169. size_t actual_size() const { return Vector<StackEntry>::size(); }
  170. size_t size() const { return m_did_insert_unknown_entry ? static_cast<size_t>(-1) : actual_size(); }
  171. Vector<StackEntry> release_vector() { return exchange(static_cast<Vector<StackEntry>&>(*this), Vector<StackEntry> {}); }
  172. bool operator==(Stack const& other) const;
  173. private:
  174. bool m_did_insert_unknown_entry { false };
  175. };
  176. struct ExpressionTypeResult {
  177. Vector<StackEntry> result_types;
  178. bool is_constant { false };
  179. };
  180. ErrorOr<ExpressionTypeResult, ValidationError> validate(Expression const&, Vector<ValueType> const&);
  181. ErrorOr<void, ValidationError> validate(Instruction const& instruction, Stack& stack, bool& is_constant);
  182. template<u32 opcode>
  183. ErrorOr<void, ValidationError> validate_instruction(Instruction const&, Stack& stack, bool& is_constant);
  184. // Types
  185. bool type_is_subtype_of(ValueType const& candidate_subtype, ValueType const& candidate_supertype);
  186. ErrorOr<void, ValidationError> validate(Limits const&, size_t k); // n <= 2^k-1 && m? <= 2^k-1
  187. ErrorOr<FunctionType, ValidationError> validate(BlockType const&);
  188. ErrorOr<void, ValidationError> validate(FunctionType const&) { return {}; }
  189. ErrorOr<void, ValidationError> validate(TableType const&);
  190. ErrorOr<void, ValidationError> validate(MemoryType const&);
  191. ErrorOr<void, ValidationError> validate(GlobalType const&) { return {}; }
  192. private:
  193. explicit Validator(Context context)
  194. : m_context(move(context))
  195. {
  196. }
  197. struct Errors {
  198. static ValidationError invalid(StringView name) { return String::formatted("Invalid {}", name); }
  199. template<typename Expected, typename Given>
  200. static ValidationError invalid(StringView name, Expected expected, Given given)
  201. {
  202. return String::formatted("Invalid {}, expected {} but got {}", name, expected, given);
  203. }
  204. template<typename... Args>
  205. static ValidationError non_conforming_types(StringView name, Args... args)
  206. {
  207. return String::formatted("Non-conforming types for {}: {}", name, Vector { args... });
  208. }
  209. static ValidationError duplicate_export_name(StringView name) { return String::formatted("Duplicate exported name '{}'", name); }
  210. template<typename T, typename U, typename V>
  211. static ValidationError out_of_bounds(StringView name, V value, T min, U max) { return String::formatted("Value {} for {} is out of bounds ({},{})", value, name, min, max); }
  212. #if WASM_VALIDATOR_DEBUG
  213. static ValidationError invalid_stack_state(SourceLocation location = SourceLocation::current());
  214. #else
  215. static ValidationError invalid_stack_state();
  216. #endif
  217. };
  218. enum class ChildScopeKind {
  219. Block,
  220. Loop,
  221. IfWithoutElse,
  222. IfWithElse,
  223. Else,
  224. };
  225. struct BlockDetails {
  226. size_t initial_stack_size { 0 };
  227. struct IfDetails {
  228. Stack initial_stack;
  229. Stack true_branch_stack;
  230. };
  231. Variant<IfDetails, Empty> details;
  232. };
  233. Context m_context;
  234. Vector<Context> m_parent_contexts;
  235. Vector<ChildScopeKind> m_entered_scopes;
  236. Vector<BlockDetails> m_block_details;
  237. Vector<FunctionType> m_entered_blocks;
  238. };
  239. }
  240. template<>
  241. struct AK::Formatter<Wasm::Validator::StackEntry> : public AK::Formatter<StringView> {
  242. ErrorOr<void> format(FormatBuilder& builder, Wasm::Validator::StackEntry const& value)
  243. {
  244. if (value.is_known)
  245. return Formatter<StringView>::format(builder, Wasm::ValueType::kind_name(value.concrete_type.kind()));
  246. return Formatter<StringView>::format(builder, "<unknown>"sv);
  247. }
  248. };
  249. template<>
  250. struct AK::Formatter<Wasm::ValueType> : public AK::Formatter<StringView> {
  251. ErrorOr<void> format(FormatBuilder& builder, Wasm::ValueType const& value)
  252. {
  253. return Formatter<StringView>::format(builder, Wasm::ValueType::kind_name(value.kind()));
  254. }
  255. };
  256. template<>
  257. struct AK::Formatter<Wasm::ValidationError> : public AK::Formatter<StringView> {
  258. ErrorOr<void> format(FormatBuilder& builder, Wasm::ValidationError const& error)
  259. {
  260. return Formatter<StringView>::format(builder, error.error_string);
  261. }
  262. };