wasm_memory.c 25 KB

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