wasm_memory.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "wasm_runtime_common.h"
  6. #include "../interpreter/wasm_runtime.h"
  7. #include "../aot/aot_runtime.h"
  8. #include "mem_alloc.h"
  9. #include "wasm_memory.h"
  10. #if WASM_ENABLE_SHARED_MEMORY != 0
  11. #include "../common/wasm_shared_memory.h"
  12. #endif
  13. typedef enum Memory_Mode {
  14. MEMORY_MODE_UNKNOWN = 0,
  15. MEMORY_MODE_POOL,
  16. MEMORY_MODE_ALLOCATOR,
  17. MEMORY_MODE_SYSTEM_ALLOCATOR
  18. } Memory_Mode;
  19. static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN;
  20. static mem_allocator_t pool_allocator = NULL;
  21. static enlarge_memory_error_callback_t enlarge_memory_error_cb;
  22. static void *enlarge_memory_error_user_data;
  23. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  24. static void *allocator_user_data = NULL;
  25. static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
  26. static void *(*realloc_func)(void *user_data, void *ptr,
  27. unsigned int size) = NULL;
  28. static void (*free_func)(void *user_data, void *ptr) = NULL;
  29. #else
  30. static void *(*malloc_func)(unsigned int size) = NULL;
  31. static void *(*realloc_func)(void *ptr, unsigned int size) = NULL;
  32. static void (*free_func)(void *ptr) = NULL;
  33. #endif
  34. static unsigned int global_pool_size;
  35. static bool
  36. wasm_memory_init_with_pool(void *mem, unsigned int bytes)
  37. {
  38. mem_allocator_t allocator = mem_allocator_create(mem, bytes);
  39. if (allocator) {
  40. memory_mode = MEMORY_MODE_POOL;
  41. pool_allocator = allocator;
  42. global_pool_size = bytes;
  43. return true;
  44. }
  45. LOG_ERROR("Init memory with pool (%p, %u) failed.\n", mem, bytes);
  46. return false;
  47. }
  48. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  49. static bool
  50. wasm_memory_init_with_allocator(void *_user_data, void *_malloc_func,
  51. void *_realloc_func, void *_free_func)
  52. {
  53. if (_malloc_func && _free_func && _malloc_func != _free_func) {
  54. memory_mode = MEMORY_MODE_ALLOCATOR;
  55. allocator_user_data = _user_data;
  56. malloc_func = _malloc_func;
  57. realloc_func = _realloc_func;
  58. free_func = _free_func;
  59. return true;
  60. }
  61. LOG_ERROR("Init memory with allocator (%p, %p, %p, %p) failed.\n",
  62. _user_data, _malloc_func, _realloc_func, _free_func);
  63. return false;
  64. }
  65. #else
  66. static bool
  67. wasm_memory_init_with_allocator(void *malloc_func_ptr, void *realloc_func_ptr,
  68. void *free_func_ptr)
  69. {
  70. if (malloc_func_ptr && free_func_ptr && malloc_func_ptr != free_func_ptr) {
  71. memory_mode = MEMORY_MODE_ALLOCATOR;
  72. malloc_func = malloc_func_ptr;
  73. realloc_func = realloc_func_ptr;
  74. free_func = free_func_ptr;
  75. return true;
  76. }
  77. LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n",
  78. malloc_func_ptr, realloc_func_ptr, free_func_ptr);
  79. return false;
  80. }
  81. #endif
  82. static inline bool
  83. is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst)
  84. {
  85. #if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0
  86. if (!module_inst) {
  87. return true;
  88. }
  89. return wasm_runtime_is_bounds_checks_enabled(module_inst);
  90. #else
  91. return true;
  92. #endif
  93. }
  94. bool
  95. wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
  96. const MemAllocOption *alloc_option)
  97. {
  98. if (mem_alloc_type == Alloc_With_Pool) {
  99. return wasm_memory_init_with_pool(alloc_option->pool.heap_buf,
  100. alloc_option->pool.heap_size);
  101. }
  102. else if (mem_alloc_type == Alloc_With_Allocator) {
  103. return wasm_memory_init_with_allocator(
  104. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  105. alloc_option->allocator.user_data,
  106. #endif
  107. alloc_option->allocator.malloc_func,
  108. alloc_option->allocator.realloc_func,
  109. alloc_option->allocator.free_func);
  110. }
  111. else if (mem_alloc_type == Alloc_With_System_Allocator) {
  112. memory_mode = MEMORY_MODE_SYSTEM_ALLOCATOR;
  113. return true;
  114. }
  115. else {
  116. return false;
  117. }
  118. }
  119. void
  120. wasm_runtime_memory_destroy()
  121. {
  122. if (memory_mode == MEMORY_MODE_POOL) {
  123. #if BH_ENABLE_GC_VERIFY == 0
  124. (void)mem_allocator_destroy(pool_allocator);
  125. #else
  126. int ret = mem_allocator_destroy(pool_allocator);
  127. if (ret != 0) {
  128. /* Memory leak detected */
  129. exit(-1);
  130. }
  131. #endif
  132. }
  133. memory_mode = MEMORY_MODE_UNKNOWN;
  134. }
  135. unsigned
  136. wasm_runtime_memory_pool_size()
  137. {
  138. if (memory_mode == MEMORY_MODE_POOL)
  139. return global_pool_size;
  140. else
  141. return UINT32_MAX;
  142. }
  143. static inline void *
  144. wasm_runtime_malloc_internal(unsigned int size)
  145. {
  146. if (memory_mode == MEMORY_MODE_UNKNOWN) {
  147. LOG_WARNING(
  148. "wasm_runtime_malloc failed: memory hasn't been initialize.\n");
  149. return NULL;
  150. }
  151. else if (memory_mode == MEMORY_MODE_POOL) {
  152. return mem_allocator_malloc(pool_allocator, size);
  153. }
  154. else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
  155. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  156. return malloc_func(allocator_user_data, size);
  157. #else
  158. return malloc_func(size);
  159. #endif
  160. }
  161. else {
  162. return os_malloc(size);
  163. }
  164. }
  165. static inline void *
  166. wasm_runtime_realloc_internal(void *ptr, unsigned int size)
  167. {
  168. if (memory_mode == MEMORY_MODE_UNKNOWN) {
  169. LOG_WARNING(
  170. "wasm_runtime_realloc failed: memory hasn't been initialize.\n");
  171. return NULL;
  172. }
  173. else if (memory_mode == MEMORY_MODE_POOL) {
  174. return mem_allocator_realloc(pool_allocator, ptr, size);
  175. }
  176. else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
  177. if (realloc_func)
  178. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  179. return realloc_func(allocator_user_data, ptr, size);
  180. #else
  181. return realloc_func(ptr, size);
  182. #endif
  183. else
  184. return NULL;
  185. }
  186. else {
  187. return os_realloc(ptr, size);
  188. }
  189. }
  190. static inline void
  191. wasm_runtime_free_internal(void *ptr)
  192. {
  193. if (!ptr) {
  194. LOG_WARNING("warning: wasm_runtime_free with NULL pointer\n");
  195. #if BH_ENABLE_GC_VERIFY != 0
  196. exit(-1);
  197. #endif
  198. return;
  199. }
  200. if (memory_mode == MEMORY_MODE_UNKNOWN) {
  201. LOG_WARNING("warning: wasm_runtime_free failed: "
  202. "memory hasn't been initialize.\n");
  203. }
  204. else if (memory_mode == MEMORY_MODE_POOL) {
  205. mem_allocator_free(pool_allocator, ptr);
  206. }
  207. else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
  208. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  209. free_func(allocator_user_data, ptr);
  210. #else
  211. free_func(ptr);
  212. #endif
  213. }
  214. else {
  215. os_free(ptr);
  216. }
  217. }
  218. void *
  219. wasm_runtime_malloc(unsigned int size)
  220. {
  221. if (size == 0) {
  222. LOG_WARNING("warning: wasm_runtime_malloc with size zero\n");
  223. /* At lease alloc 1 byte to avoid malloc failed */
  224. size = 1;
  225. #if BH_ENABLE_GC_VERIFY != 0
  226. exit(-1);
  227. #endif
  228. }
  229. return wasm_runtime_malloc_internal(size);
  230. }
  231. void *
  232. wasm_runtime_realloc(void *ptr, unsigned int size)
  233. {
  234. return wasm_runtime_realloc_internal(ptr, size);
  235. }
  236. void
  237. wasm_runtime_free(void *ptr)
  238. {
  239. wasm_runtime_free_internal(ptr);
  240. }
  241. bool
  242. wasm_runtime_get_mem_alloc_info(mem_alloc_info_t *mem_alloc_info)
  243. {
  244. if (memory_mode == MEMORY_MODE_POOL) {
  245. return mem_allocator_get_alloc_info(pool_allocator, mem_alloc_info);
  246. }
  247. return false;
  248. }
  249. bool
  250. wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
  251. uint32 app_offset, uint32 size)
  252. {
  253. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  254. WASMMemoryInstance *memory_inst;
  255. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  256. || module_inst_comm->module_type == Wasm_Module_AoT);
  257. if (!is_bounds_checks_enabled(module_inst_comm)) {
  258. return true;
  259. }
  260. memory_inst = wasm_get_default_memory(module_inst);
  261. if (!memory_inst) {
  262. goto fail;
  263. }
  264. /* integer overflow check */
  265. if (app_offset > UINT32_MAX - size) {
  266. goto fail;
  267. }
  268. SHARED_MEMORY_LOCK(memory_inst);
  269. if (app_offset + size <= memory_inst->memory_data_size) {
  270. SHARED_MEMORY_UNLOCK(memory_inst);
  271. return true;
  272. }
  273. SHARED_MEMORY_UNLOCK(memory_inst);
  274. fail:
  275. wasm_set_exception(module_inst, "out of bounds memory access");
  276. return false;
  277. }
  278. bool
  279. wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
  280. uint32 app_str_offset)
  281. {
  282. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  283. uint32 app_end_offset;
  284. char *str, *str_end;
  285. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  286. || module_inst_comm->module_type == Wasm_Module_AoT);
  287. if (!is_bounds_checks_enabled(module_inst_comm)) {
  288. return true;
  289. }
  290. if (!wasm_runtime_get_app_addr_range(module_inst_comm, app_str_offset, NULL,
  291. &app_end_offset))
  292. goto fail;
  293. str = wasm_runtime_addr_app_to_native(module_inst_comm, app_str_offset);
  294. str_end = str + (app_end_offset - app_str_offset);
  295. while (str < str_end && *str != '\0')
  296. str++;
  297. if (str == str_end)
  298. goto fail;
  299. return true;
  300. fail:
  301. wasm_set_exception(module_inst, "out of bounds memory access");
  302. return false;
  303. }
  304. bool
  305. wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
  306. void *native_ptr, uint32 size)
  307. {
  308. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  309. WASMMemoryInstance *memory_inst;
  310. uint8 *addr = (uint8 *)native_ptr;
  311. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  312. || module_inst_comm->module_type == Wasm_Module_AoT);
  313. if (!is_bounds_checks_enabled(module_inst_comm)) {
  314. return true;
  315. }
  316. memory_inst = wasm_get_default_memory(module_inst);
  317. if (!memory_inst) {
  318. goto fail;
  319. }
  320. /* integer overflow check */
  321. if ((uintptr_t)addr > UINTPTR_MAX - size) {
  322. goto fail;
  323. }
  324. SHARED_MEMORY_LOCK(memory_inst);
  325. if (memory_inst->memory_data <= addr
  326. && addr + size <= memory_inst->memory_data_end) {
  327. SHARED_MEMORY_UNLOCK(memory_inst);
  328. return true;
  329. }
  330. SHARED_MEMORY_UNLOCK(memory_inst);
  331. fail:
  332. wasm_set_exception(module_inst, "out of bounds memory access");
  333. return false;
  334. }
  335. void *
  336. wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
  337. uint32 app_offset)
  338. {
  339. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  340. WASMMemoryInstance *memory_inst;
  341. uint8 *addr;
  342. bool bounds_checks;
  343. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  344. || module_inst_comm->module_type == Wasm_Module_AoT);
  345. bounds_checks = is_bounds_checks_enabled(module_inst_comm);
  346. memory_inst = wasm_get_default_memory(module_inst);
  347. if (!memory_inst) {
  348. return NULL;
  349. }
  350. SHARED_MEMORY_LOCK(memory_inst);
  351. addr = memory_inst->memory_data + app_offset;
  352. if (bounds_checks) {
  353. if (memory_inst->memory_data <= addr
  354. && addr < memory_inst->memory_data_end) {
  355. SHARED_MEMORY_UNLOCK(memory_inst);
  356. return addr;
  357. }
  358. }
  359. /* If bounds checks is disabled, return the address directly */
  360. else if (app_offset != 0) {
  361. SHARED_MEMORY_UNLOCK(memory_inst);
  362. return addr;
  363. }
  364. SHARED_MEMORY_UNLOCK(memory_inst);
  365. return NULL;
  366. }
  367. uint32
  368. wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
  369. void *native_ptr)
  370. {
  371. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  372. WASMMemoryInstance *memory_inst;
  373. uint8 *addr = (uint8 *)native_ptr;
  374. bool bounds_checks;
  375. uint32 ret;
  376. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  377. || module_inst_comm->module_type == Wasm_Module_AoT);
  378. bounds_checks = is_bounds_checks_enabled(module_inst_comm);
  379. memory_inst = wasm_get_default_memory(module_inst);
  380. if (!memory_inst) {
  381. return 0;
  382. }
  383. SHARED_MEMORY_LOCK(memory_inst);
  384. if (bounds_checks) {
  385. if (memory_inst->memory_data <= addr
  386. && addr < memory_inst->memory_data_end) {
  387. ret = (uint32)(addr - memory_inst->memory_data);
  388. SHARED_MEMORY_UNLOCK(memory_inst);
  389. return ret;
  390. }
  391. }
  392. /* If bounds checks is disabled, return the offset directly */
  393. else if (addr != NULL) {
  394. ret = (uint32)(addr - memory_inst->memory_data);
  395. SHARED_MEMORY_UNLOCK(memory_inst);
  396. return ret;
  397. }
  398. SHARED_MEMORY_UNLOCK(memory_inst);
  399. return 0;
  400. }
  401. bool
  402. wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm,
  403. uint32 app_offset, uint32 *p_app_start_offset,
  404. uint32 *p_app_end_offset)
  405. {
  406. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  407. WASMMemoryInstance *memory_inst;
  408. uint32 memory_data_size;
  409. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  410. || module_inst_comm->module_type == Wasm_Module_AoT);
  411. memory_inst = wasm_get_default_memory(module_inst);
  412. if (!memory_inst) {
  413. return false;
  414. }
  415. SHARED_MEMORY_LOCK(memory_inst);
  416. memory_data_size = memory_inst->memory_data_size;
  417. if (app_offset < memory_data_size) {
  418. if (p_app_start_offset)
  419. *p_app_start_offset = 0;
  420. if (p_app_end_offset)
  421. *p_app_end_offset = memory_data_size;
  422. SHARED_MEMORY_UNLOCK(memory_inst);
  423. return true;
  424. }
  425. SHARED_MEMORY_UNLOCK(memory_inst);
  426. return false;
  427. }
  428. bool
  429. wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst_comm,
  430. uint8 *native_ptr,
  431. uint8 **p_native_start_addr,
  432. uint8 **p_native_end_addr)
  433. {
  434. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  435. WASMMemoryInstance *memory_inst;
  436. uint8 *addr = (uint8 *)native_ptr;
  437. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  438. || module_inst_comm->module_type == Wasm_Module_AoT);
  439. memory_inst = wasm_get_default_memory(module_inst);
  440. if (!memory_inst) {
  441. return false;
  442. }
  443. SHARED_MEMORY_LOCK(memory_inst);
  444. if (memory_inst->memory_data <= addr
  445. && addr < memory_inst->memory_data_end) {
  446. if (p_native_start_addr)
  447. *p_native_start_addr = memory_inst->memory_data;
  448. if (p_native_end_addr)
  449. *p_native_end_addr = memory_inst->memory_data_end;
  450. SHARED_MEMORY_UNLOCK(memory_inst);
  451. return true;
  452. }
  453. SHARED_MEMORY_UNLOCK(memory_inst);
  454. return false;
  455. }
  456. bool
  457. wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
  458. uint32 app_buf_addr, uint32 app_buf_size,
  459. void **p_native_addr)
  460. {
  461. WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst);
  462. uint8 *native_addr;
  463. bool bounds_checks;
  464. if (!memory_inst) {
  465. wasm_set_exception(module_inst, "out of bounds memory access");
  466. return false;
  467. }
  468. native_addr = memory_inst->memory_data + app_buf_addr;
  469. bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst);
  470. if (!bounds_checks) {
  471. if (app_buf_addr == 0) {
  472. native_addr = NULL;
  473. }
  474. goto success;
  475. }
  476. /* No need to check the app_offset and buf_size if memory access
  477. boundary check with hardware trap is enabled */
  478. #ifndef OS_ENABLE_HW_BOUND_CHECK
  479. SHARED_MEMORY_LOCK(memory_inst);
  480. if (app_buf_addr >= memory_inst->memory_data_size) {
  481. goto fail;
  482. }
  483. if (!is_str) {
  484. if (app_buf_size > memory_inst->memory_data_size - app_buf_addr) {
  485. goto fail;
  486. }
  487. }
  488. else {
  489. const char *str, *str_end;
  490. /* The whole string must be in the linear memory */
  491. str = (const char *)native_addr;
  492. str_end = (const char *)memory_inst->memory_data_end;
  493. while (str < str_end && *str != '\0')
  494. str++;
  495. if (str == str_end)
  496. goto fail;
  497. }
  498. SHARED_MEMORY_UNLOCK(memory_inst);
  499. #endif
  500. success:
  501. *p_native_addr = (void *)native_addr;
  502. return true;
  503. #ifndef OS_ENABLE_HW_BOUND_CHECK
  504. fail:
  505. SHARED_MEMORY_UNLOCK(memory_inst);
  506. wasm_set_exception(module_inst, "out of bounds memory access");
  507. return false;
  508. #endif
  509. }
  510. WASMMemoryInstance *
  511. wasm_get_default_memory(WASMModuleInstance *module_inst)
  512. {
  513. if (module_inst->memories)
  514. return module_inst->memories[0];
  515. else
  516. return NULL;
  517. }
  518. void
  519. wasm_runtime_set_mem_bound_check_bytes(WASMMemoryInstance *memory,
  520. uint64 memory_data_size)
  521. {
  522. #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
  523. #if UINTPTR_MAX == UINT64_MAX
  524. memory->mem_bound_check_1byte.u64 = memory_data_size - 1;
  525. memory->mem_bound_check_2bytes.u64 = memory_data_size - 2;
  526. memory->mem_bound_check_4bytes.u64 = memory_data_size - 4;
  527. memory->mem_bound_check_8bytes.u64 = memory_data_size - 8;
  528. memory->mem_bound_check_16bytes.u64 = memory_data_size - 16;
  529. #else
  530. memory->mem_bound_check_1byte.u32[0] = (uint32)memory_data_size - 1;
  531. memory->mem_bound_check_2bytes.u32[0] = (uint32)memory_data_size - 2;
  532. memory->mem_bound_check_4bytes.u32[0] = (uint32)memory_data_size - 4;
  533. memory->mem_bound_check_8bytes.u32[0] = (uint32)memory_data_size - 8;
  534. memory->mem_bound_check_16bytes.u32[0] = (uint32)memory_data_size - 16;
  535. #endif
  536. #endif
  537. }
  538. #ifndef OS_ENABLE_HW_BOUND_CHECK
  539. bool
  540. wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
  541. {
  542. WASMMemoryInstance *memory = wasm_get_default_memory(module);
  543. uint8 *memory_data_old, *memory_data_new, *heap_data_old;
  544. uint32 num_bytes_per_page, heap_size, total_size_old = 0;
  545. uint32 cur_page_count, max_page_count, total_page_count;
  546. uint64 total_size_new;
  547. bool ret = true;
  548. enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR;
  549. if (!memory) {
  550. ret = false;
  551. goto return_func;
  552. }
  553. heap_data_old = memory->heap_data;
  554. heap_size = (uint32)(memory->heap_data_end - memory->heap_data);
  555. memory_data_old = memory->memory_data;
  556. total_size_old = memory->memory_data_size;
  557. num_bytes_per_page = memory->num_bytes_per_page;
  558. cur_page_count = memory->cur_page_count;
  559. max_page_count = memory->max_page_count;
  560. total_page_count = inc_page_count + cur_page_count;
  561. total_size_new = num_bytes_per_page * (uint64)total_page_count;
  562. if (inc_page_count <= 0)
  563. /* No need to enlarge memory */
  564. return true;
  565. if (total_page_count < cur_page_count) { /* integer overflow */
  566. ret = false;
  567. goto return_func;
  568. }
  569. if (total_page_count > max_page_count) {
  570. failure_reason = MAX_SIZE_REACHED;
  571. ret = false;
  572. goto return_func;
  573. }
  574. bh_assert(total_size_new <= 4 * (uint64)BH_GB);
  575. if (total_size_new > UINT32_MAX) {
  576. /* Resize to 1 page with size 4G-1 */
  577. num_bytes_per_page = UINT32_MAX;
  578. total_page_count = max_page_count = 1;
  579. total_size_new = UINT32_MAX;
  580. }
  581. #if WASM_ENABLE_SHARED_MEMORY != 0
  582. if (shared_memory_is_shared(memory)) {
  583. memory->num_bytes_per_page = num_bytes_per_page;
  584. memory->cur_page_count = total_page_count;
  585. memory->max_page_count = max_page_count;
  586. SET_LINEAR_MEMORY_SIZE(memory, (uint32)total_size_new);
  587. memory->memory_data_end = memory->memory_data + (uint32)total_size_new;
  588. wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new);
  589. return true;
  590. }
  591. #endif
  592. if (heap_size > 0) {
  593. if (mem_allocator_is_heap_corrupted(memory->heap_handle)) {
  594. wasm_runtime_show_app_heap_corrupted_prompt();
  595. ret = false;
  596. goto return_func;
  597. }
  598. }
  599. if (!(memory_data_new =
  600. wasm_runtime_realloc(memory_data_old, (uint32)total_size_new))) {
  601. if (!(memory_data_new = wasm_runtime_malloc((uint32)total_size_new))) {
  602. ret = false;
  603. goto return_func;
  604. }
  605. if (memory_data_old) {
  606. bh_memcpy_s(memory_data_new, (uint32)total_size_new,
  607. memory_data_old, total_size_old);
  608. wasm_runtime_free(memory_data_old);
  609. }
  610. }
  611. memset(memory_data_new + total_size_old, 0,
  612. (uint32)total_size_new - total_size_old);
  613. if (heap_size > 0) {
  614. if (mem_allocator_migrate(memory->heap_handle,
  615. (char *)heap_data_old
  616. + (memory_data_new - memory_data_old),
  617. heap_size)
  618. != 0) {
  619. /* Don't return here as memory->memory_data is obsolete and
  620. must be updated to be correctly used later. */
  621. ret = false;
  622. }
  623. }
  624. memory->heap_data = memory_data_new + (heap_data_old - memory_data_old);
  625. memory->heap_data_end = memory->heap_data + heap_size;
  626. memory->num_bytes_per_page = num_bytes_per_page;
  627. memory->cur_page_count = total_page_count;
  628. memory->max_page_count = max_page_count;
  629. memory->memory_data_size = (uint32)total_size_new;
  630. memory->memory_data = memory_data_new;
  631. memory->memory_data_end = memory_data_new + (uint32)total_size_new;
  632. wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new);
  633. #if defined(os_writegsbase)
  634. /* write base addr of linear memory to GS segment register */
  635. os_writegsbase(memory_data_new);
  636. #endif
  637. return_func:
  638. if (!ret && enlarge_memory_error_cb) {
  639. WASMExecEnv *exec_env = NULL;
  640. #if WASM_ENABLE_INTERP != 0
  641. if (module->module_type == Wasm_Module_Bytecode)
  642. exec_env =
  643. ((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env;
  644. #endif
  645. #if WASM_ENABLE_AOT != 0
  646. if (module->module_type == Wasm_Module_AoT)
  647. exec_env =
  648. ((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env;
  649. #endif
  650. enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
  651. failure_reason,
  652. (WASMModuleInstanceCommon *)module, exec_env,
  653. enlarge_memory_error_user_data);
  654. }
  655. return ret;
  656. }
  657. #else
  658. bool
  659. wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
  660. {
  661. WASMMemoryInstance *memory = wasm_get_default_memory(module);
  662. uint32 num_bytes_per_page, total_size_old = 0;
  663. uint32 cur_page_count, max_page_count, total_page_count;
  664. uint64 total_size_new;
  665. bool ret = true;
  666. enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR;
  667. if (!memory) {
  668. ret = false;
  669. goto return_func;
  670. }
  671. num_bytes_per_page = memory->num_bytes_per_page;
  672. cur_page_count = memory->cur_page_count;
  673. max_page_count = memory->max_page_count;
  674. total_size_old = num_bytes_per_page * cur_page_count;
  675. total_page_count = inc_page_count + cur_page_count;
  676. total_size_new = num_bytes_per_page * (uint64)total_page_count;
  677. if (inc_page_count <= 0)
  678. /* No need to enlarge memory */
  679. return true;
  680. if (total_page_count < cur_page_count) { /* integer overflow */
  681. ret = false;
  682. goto return_func;
  683. }
  684. if (total_page_count > max_page_count) {
  685. failure_reason = MAX_SIZE_REACHED;
  686. ret = false;
  687. goto return_func;
  688. }
  689. bh_assert(total_size_new <= 4 * (uint64)BH_GB);
  690. if (total_size_new > UINT32_MAX) {
  691. /* Resize to 1 page with size 4G-1 */
  692. num_bytes_per_page = UINT32_MAX;
  693. total_page_count = max_page_count = 1;
  694. total_size_new = UINT32_MAX;
  695. }
  696. #ifdef BH_PLATFORM_WINDOWS
  697. if (!os_mem_commit(memory->memory_data_end,
  698. (uint32)total_size_new - total_size_old,
  699. MMAP_PROT_READ | MMAP_PROT_WRITE)) {
  700. ret = false;
  701. goto return_func;
  702. }
  703. #endif
  704. if (os_mprotect(memory->memory_data_end,
  705. (uint32)total_size_new - total_size_old,
  706. MMAP_PROT_READ | MMAP_PROT_WRITE)
  707. != 0) {
  708. #ifdef BH_PLATFORM_WINDOWS
  709. os_mem_decommit(memory->memory_data_end,
  710. (uint32)total_size_new - total_size_old);
  711. #endif
  712. ret = false;
  713. goto return_func;
  714. }
  715. /* The increased pages are filled with zero by the OS when os_mmap,
  716. no need to memset it again here */
  717. memory->num_bytes_per_page = num_bytes_per_page;
  718. memory->cur_page_count = total_page_count;
  719. memory->max_page_count = max_page_count;
  720. SET_LINEAR_MEMORY_SIZE(memory, (uint32)total_size_new);
  721. memory->memory_data_end = memory->memory_data + (uint32)total_size_new;
  722. wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new);
  723. return_func:
  724. if (!ret && enlarge_memory_error_cb) {
  725. WASMExecEnv *exec_env = NULL;
  726. #if WASM_ENABLE_INTERP != 0
  727. if (module->module_type == Wasm_Module_Bytecode)
  728. exec_env =
  729. ((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env;
  730. #endif
  731. #if WASM_ENABLE_AOT != 0
  732. if (module->module_type == Wasm_Module_AoT)
  733. exec_env =
  734. ((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env;
  735. #endif
  736. enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
  737. failure_reason,
  738. (WASMModuleInstanceCommon *)module, exec_env,
  739. enlarge_memory_error_user_data);
  740. }
  741. return ret;
  742. }
  743. #endif /* end of OS_ENABLE_HW_BOUND_CHECK */
  744. void
  745. wasm_runtime_set_enlarge_mem_error_callback(
  746. const enlarge_memory_error_callback_t callback, void *user_data)
  747. {
  748. enlarge_memory_error_cb = callback;
  749. enlarge_memory_error_user_data = user_data;
  750. }
  751. bool
  752. wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
  753. {
  754. bool ret = false;
  755. #if WASM_ENABLE_SHARED_MEMORY != 0
  756. if (module->memory_count > 0)
  757. shared_memory_lock(module->memories[0]);
  758. #endif
  759. ret = wasm_enlarge_memory_internal(module, inc_page_count);
  760. #if WASM_ENABLE_SHARED_MEMORY != 0
  761. if (module->memory_count > 0)
  762. shared_memory_unlock(module->memories[0]);
  763. #endif
  764. return ret;
  765. }