wasm_loader_common.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright (C) 2024 Amazon Inc. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "wasm_loader_common.h"
  6. #include "bh_leb128.h"
  7. #include "bh_log.h"
  8. #if WASM_ENABLE_GC != 0
  9. #include "../common/gc/gc_type.h"
  10. #endif
  11. void
  12. wasm_loader_set_error_buf(char *error_buf, uint32 error_buf_size,
  13. const char *string, bool is_aot)
  14. {
  15. if (error_buf != NULL) {
  16. snprintf(error_buf, error_buf_size, "%s module load failed: %s",
  17. is_aot ? "AOT" : "WASM", string);
  18. }
  19. }
  20. bool
  21. wasm_memory_check_flags(const uint8 mem_flag, char *error_buf,
  22. uint32 error_buf_size, bool is_aot)
  23. {
  24. /* Check whether certain features indicated by mem_flag are enabled in
  25. * runtime */
  26. if (mem_flag > MAX_PAGE_COUNT_FLAG) {
  27. #if WASM_ENABLE_SHARED_MEMORY == 0
  28. if (mem_flag & SHARED_MEMORY_FLAG) {
  29. LOG_VERBOSE("shared memory flag was found, please enable shared "
  30. "memory, lib-pthread or lib-wasi-threads");
  31. wasm_loader_set_error_buf(error_buf, error_buf_size,
  32. "invalid limits flags", is_aot);
  33. return false;
  34. }
  35. #endif
  36. #if WASM_ENABLE_MEMORY64 == 0
  37. if (mem_flag & MEMORY64_FLAG) {
  38. LOG_VERBOSE("memory64 flag was found, please enable memory64");
  39. wasm_loader_set_error_buf(error_buf, error_buf_size,
  40. "invalid limits flags", is_aot);
  41. return false;
  42. }
  43. #endif
  44. }
  45. if (mem_flag > MAX_PAGE_COUNT_FLAG + SHARED_MEMORY_FLAG + MEMORY64_FLAG) {
  46. wasm_loader_set_error_buf(error_buf, error_buf_size,
  47. "invalid limits flags", is_aot);
  48. return false;
  49. }
  50. else if ((mem_flag & SHARED_MEMORY_FLAG)
  51. && !(mem_flag & MAX_PAGE_COUNT_FLAG)) {
  52. wasm_loader_set_error_buf(error_buf, error_buf_size,
  53. "shared memory must have maximum", is_aot);
  54. return false;
  55. }
  56. return true;
  57. }
  58. /*
  59. * compare with a bigger type set in `wasm_value_type_size_internal()`,
  60. * this function will only cover global value type, function's param
  61. * value type and function's result value type.
  62. *
  63. * please feel free to add more if there are more requirements
  64. */
  65. bool
  66. is_valid_value_type(uint8 type)
  67. {
  68. if (/* I32/I64/F32/F64, 0x7C to 0x7F */
  69. (type >= VALUE_TYPE_F64 && type <= VALUE_TYPE_I32)
  70. #if WASM_ENABLE_GC != 0
  71. /* reference types, 0x65 to 0x70 */
  72. || wasm_is_type_reftype(type)
  73. #elif WASM_ENABLE_REF_TYPES != 0
  74. || (type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF)
  75. #endif
  76. #if WASM_ENABLE_SIMD != 0
  77. || type == VALUE_TYPE_V128 /* 0x7B */
  78. #endif
  79. )
  80. return true;
  81. return false;
  82. }
  83. bool
  84. is_valid_value_type_for_interpreter(uint8 value_type)
  85. {
  86. #if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0)
  87. /*
  88. * Note: regardless of WASM_ENABLE_SIMD, our interpreters don't have
  89. * SIMD implemented. It's safer to reject v128, especially for the
  90. * fast interpreter.
  91. */
  92. if (value_type == VALUE_TYPE_V128)
  93. return false;
  94. #endif
  95. return is_valid_value_type(value_type);
  96. }
  97. bool
  98. is_valid_func_type(const WASMFuncType *func_type)
  99. {
  100. unsigned i;
  101. for (i = 0;
  102. i < (unsigned)(func_type->param_count + func_type->result_count);
  103. i++) {
  104. if (!is_valid_value_type(func_type->types[i]))
  105. return false;
  106. }
  107. return true;
  108. }
  109. /*
  110. * Indices are represented as a u32.
  111. */
  112. bool
  113. is_indices_overflow(uint32 import, uint32 other, char *error_buf,
  114. uint32 error_buf_size)
  115. {
  116. if (import > UINT32_MAX - other) {
  117. snprintf(error_buf, error_buf_size,
  118. "too many items in the index space(%" PRIu32 "+%" PRIu32 ").",
  119. import, other);
  120. return true;
  121. }
  122. return false;
  123. }
  124. bool
  125. read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
  126. uint64 *p_result, char *error_buf, uint32 error_buf_size)
  127. {
  128. size_t offset = 0;
  129. bh_leb_read_status_t status =
  130. bh_leb_read(*p_buf, buf_end, maxbits, sign, p_result, &offset);
  131. switch (status) {
  132. case BH_LEB_READ_SUCCESS:
  133. *p_buf += offset;
  134. return true;
  135. case BH_LEB_READ_TOO_LONG:
  136. wasm_loader_set_error_buf(error_buf, error_buf_size,
  137. "integer representation too long", false);
  138. return false;
  139. case BH_LEB_READ_OVERFLOW:
  140. wasm_loader_set_error_buf(error_buf, error_buf_size,
  141. "integer too large", false);
  142. return false;
  143. case BH_LEB_READ_UNEXPECTED_END:
  144. wasm_loader_set_error_buf(error_buf, error_buf_size,
  145. "unexpected end", false);
  146. return false;
  147. default:
  148. bh_assert(false);
  149. return false;
  150. }
  151. }