shared_heap_test.cc 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. /*
  2. * Copyright (C) 2024 Xiaomi Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "test_helper.h"
  6. #include "gtest/gtest.h"
  7. #include "bh_read_file.h"
  8. #include "wasm_runtime_common.h"
  9. #include <gtest/gtest-spi.h>
  10. class shared_heap_test : public testing::Test
  11. {
  12. protected:
  13. virtual void SetUp() {}
  14. static void SetUpTestCase() {}
  15. virtual void TearDown() {}
  16. WAMRRuntimeRAII<512 * 1024> runtime;
  17. };
  18. struct ret_env {
  19. wasm_exec_env_t exec_env;
  20. wasm_module_t wasm_module;
  21. wasm_module_inst_t wasm_module_inst;
  22. unsigned char *wasm_file_buf;
  23. char error_buf[128];
  24. };
  25. static void
  26. destroy_module_env(struct ret_env module_env);
  27. static bool
  28. load_wasm(char *wasm_file_tested, unsigned int app_heap_size,
  29. ret_env &ret_module_env)
  30. {
  31. char *wasm_file = strdup(wasm_file_tested);
  32. unsigned int wasm_file_size = 0;
  33. unsigned int stack_size = 16 * 1024, heap_size = app_heap_size;
  34. char error_buf[128] = { 0 };
  35. ret_module_env.wasm_file_buf =
  36. (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
  37. if (!ret_module_env.wasm_file_buf) {
  38. goto fail;
  39. }
  40. ret_module_env.wasm_module =
  41. wasm_runtime_load(ret_module_env.wasm_file_buf, wasm_file_size,
  42. error_buf, sizeof(error_buf));
  43. if (!ret_module_env.wasm_module) {
  44. memcpy(ret_module_env.error_buf, error_buf, 128);
  45. goto fail;
  46. }
  47. ret_module_env.wasm_module_inst =
  48. wasm_runtime_instantiate(ret_module_env.wasm_module, stack_size,
  49. heap_size, error_buf, sizeof(error_buf));
  50. if (!ret_module_env.wasm_module_inst) {
  51. memcpy(ret_module_env.error_buf, error_buf, 128);
  52. goto fail;
  53. }
  54. ret_module_env.exec_env = wasm_runtime_create_exec_env(
  55. ret_module_env.wasm_module_inst, stack_size);
  56. if (!ret_module_env.exec_env) {
  57. goto fail;
  58. }
  59. free(wasm_file);
  60. return true;
  61. fail:
  62. free(wasm_file);
  63. destroy_module_env(ret_module_env);
  64. return false;
  65. }
  66. void
  67. destroy_module_env(struct ret_env module_env)
  68. {
  69. if (module_env.exec_env) {
  70. wasm_runtime_destroy_exec_env(module_env.exec_env);
  71. }
  72. if (module_env.wasm_module_inst) {
  73. wasm_runtime_deinstantiate(module_env.wasm_module_inst);
  74. }
  75. if (module_env.wasm_module) {
  76. wasm_runtime_unload(module_env.wasm_module);
  77. }
  78. if (module_env.wasm_file_buf) {
  79. wasm_runtime_free(module_env.wasm_file_buf);
  80. }
  81. }
  82. static void
  83. test_shared_heap(WASMSharedHeap *shared_heap, const char *file,
  84. const char *func_name, uint32 argc, uint32 argv[])
  85. {
  86. struct ret_env tmp_module_env;
  87. WASMFunctionInstanceCommon *func_test = nullptr;
  88. bool ret = false;
  89. if (!load_wasm((char *)file, 0, tmp_module_env)) {
  90. ADD_FAILURE() << "Failed to load wasm file\n";
  91. goto fail0;
  92. }
  93. if (!wasm_runtime_attach_shared_heap(tmp_module_env.wasm_module_inst,
  94. shared_heap)) {
  95. ADD_FAILURE() << "Failed to attach shared heap\n";
  96. goto fail1;
  97. }
  98. func_test = wasm_runtime_lookup_function(tmp_module_env.wasm_module_inst,
  99. func_name);
  100. if (!func_test) {
  101. ADD_FAILURE() << "Failed to wasm_runtime_lookup_function!\n";
  102. goto fail2;
  103. }
  104. ret =
  105. wasm_runtime_call_wasm(tmp_module_env.exec_env, func_test, argc, argv);
  106. if (!ret) {
  107. const char *s =
  108. wasm_runtime_get_exception(tmp_module_env.wasm_module_inst);
  109. ADD_FAILURE() << "Failed to wasm_runtime_call_wasm with "
  110. << "exception: " << s;
  111. }
  112. fail2:
  113. wasm_runtime_detach_shared_heap(tmp_module_env.wasm_module_inst);
  114. fail1:
  115. destroy_module_env(tmp_module_env);
  116. fail0:
  117. return;
  118. }
  119. TEST_F(shared_heap_test, test_shared_heap_basic)
  120. {
  121. SharedHeapInitArgs args = { 0 };
  122. WASMSharedHeap *shared_heap = nullptr;
  123. uint32 argv[1] = { 0 };
  124. args.size = 1024;
  125. shared_heap = wasm_runtime_create_shared_heap(&args);
  126. if (!shared_heap) {
  127. FAIL() << "Failed to create shared heap";
  128. }
  129. test_shared_heap(shared_heap, "test.wasm", "test", 0, argv);
  130. EXPECT_EQ(10, argv[0]);
  131. test_shared_heap(shared_heap, "test.aot", "test", 0, argv);
  132. EXPECT_EQ(10, argv[0]);
  133. test_shared_heap(shared_heap, "test_chain.aot", "test", 0, argv);
  134. EXPECT_EQ(10, argv[0]);
  135. }
  136. TEST_F(shared_heap_test, test_shared_heap_malloc_fail)
  137. {
  138. SharedHeapInitArgs args = { 0 };
  139. WASMSharedHeap *shared_heap = nullptr;
  140. uint32 argv[1] = { 0 };
  141. args.size = 1024;
  142. shared_heap = wasm_runtime_create_shared_heap(&args);
  143. if (!shared_heap) {
  144. FAIL() << "Failed to create shared heap";
  145. }
  146. test_shared_heap(shared_heap, "test.wasm", "test_malloc_fail", 0, argv);
  147. EXPECT_EQ(1, argv[0]);
  148. test_shared_heap(shared_heap, "test.aot", "test_malloc_fail", 0, argv);
  149. EXPECT_EQ(1, argv[0]);
  150. test_shared_heap(shared_heap, "test_chain.aot", "test_malloc_fail", 0,
  151. argv);
  152. EXPECT_EQ(1, argv[0]);
  153. }
  154. TEST_F(shared_heap_test, test_preallocated_shared_heap_malloc_fail)
  155. {
  156. SharedHeapInitArgs args = { 0 };
  157. WASMSharedHeap *shared_heap = nullptr;
  158. uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize();
  159. uint8 preallocated_buf[BUF_SIZE];
  160. /* create a preallocated shared heap */
  161. args.pre_allocated_addr = preallocated_buf;
  162. args.size = BUF_SIZE;
  163. shared_heap = wasm_runtime_create_shared_heap(&args);
  164. if (!shared_heap) {
  165. FAIL() << "Create preallocated shared heap failed.\n";
  166. }
  167. /* test wasm can't malloc with preallocated shared heap */
  168. argv[0] = 1024;
  169. test_shared_heap(shared_heap, "test.wasm", "my_shared_heap_malloc", 1,
  170. argv);
  171. EXPECT_EQ(0, argv[0]);
  172. argv[0] = 1024;
  173. test_shared_heap(shared_heap, "test.aot", "my_shared_heap_malloc", 1, argv);
  174. EXPECT_EQ(0, argv[0]);
  175. argv[0] = 1024;
  176. test_shared_heap(shared_heap, "test_chain.aot", "my_shared_heap_malloc", 1,
  177. argv);
  178. EXPECT_EQ(0, argv[0]);
  179. }
  180. static void
  181. create_test_shared_heap(uint8 *preallocated_buf, size_t size,
  182. WASMSharedHeap **shared_heap_res)
  183. {
  184. SharedHeapInitArgs args = { 0 };
  185. WASMSharedHeap *shared_heap = nullptr;
  186. args.pre_allocated_addr = preallocated_buf;
  187. args.size = size;
  188. shared_heap = wasm_runtime_create_shared_heap(&args);
  189. if (!shared_heap) {
  190. FAIL() << "Create preallocated shared heap failed.\n";
  191. }
  192. *shared_heap_res = shared_heap;
  193. if (!*shared_heap_res) {
  194. FAIL() << "Create shared heap chain failed.\n";
  195. }
  196. }
  197. static void
  198. create_test_shared_heap_chain(uint8 *preallocated_buf, size_t size,
  199. uint8 *preallocated_buf2, size_t size2,
  200. WASMSharedHeap **shared_heap_chain)
  201. {
  202. SharedHeapInitArgs args = { 0 };
  203. WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr;
  204. args.pre_allocated_addr = preallocated_buf;
  205. args.size = size;
  206. shared_heap = wasm_runtime_create_shared_heap(&args);
  207. if (!shared_heap) {
  208. FAIL() << "Create preallocated shared heap failed.\n";
  209. }
  210. memset(&args, 0, sizeof(args));
  211. args.pre_allocated_addr = preallocated_buf2;
  212. args.size = size2;
  213. shared_heap2 = wasm_runtime_create_shared_heap(&args);
  214. if (!shared_heap2) {
  215. FAIL() << "Create preallocated shared heap failed.\n";
  216. }
  217. *shared_heap_chain =
  218. wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
  219. if (!*shared_heap_chain) {
  220. FAIL() << "Create shared heap chain failed.\n";
  221. }
  222. }
  223. TEST_F(shared_heap_test, test_shared_heap_rmw)
  224. {
  225. WASMSharedHeap *shared_heap = nullptr;
  226. uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
  227. uint8 preallocated_buf[BUF_SIZE] = { 0 };
  228. uint32 start1, end1;
  229. create_test_shared_heap(preallocated_buf, BUF_SIZE, &shared_heap);
  230. /* app addr for shared heap */
  231. start1 = UINT32_MAX - BUF_SIZE + 1;
  232. end1 = UINT32_MAX;
  233. argv[0] = end1;
  234. argv[1] = 101;
  235. test_shared_heap(shared_heap, "test.wasm", "read_modify_write_8", 2, argv);
  236. EXPECT_EQ(0, argv[0]);
  237. EXPECT_EQ(preallocated_buf[BUF_SIZE - 1], 101);
  238. argv[0] = start1;
  239. argv[1] = 37;
  240. test_shared_heap(shared_heap, "test.wasm", "read_modify_write_8", 2, argv);
  241. EXPECT_EQ(0, argv[0]);
  242. EXPECT_EQ(preallocated_buf[0], 37);
  243. argv[0] = end1;
  244. argv[1] = 81;
  245. test_shared_heap(shared_heap, "test.aot", "read_modify_write_8", 2, argv);
  246. EXPECT_EQ(101, argv[0]);
  247. EXPECT_EQ(preallocated_buf[BUF_SIZE - 1], 81);
  248. argv[0] = start1;
  249. argv[1] = 98;
  250. test_shared_heap(shared_heap, "test.aot", "read_modify_write_8", 2, argv);
  251. EXPECT_EQ(37, argv[0]);
  252. EXPECT_EQ(preallocated_buf[0], 98);
  253. }
  254. TEST_F(shared_heap_test, test_shared_heap_chain_rmw)
  255. {
  256. SharedHeapInitArgs args = { 0 };
  257. WASMSharedHeap *shared_heap_chain = nullptr;
  258. uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
  259. uint8 preallocated_buf[BUF_SIZE] = { 0 },
  260. preallocated_buf2[BUF_SIZE] = { 0 };
  261. uint32 start1, end1, start2, end2;
  262. create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
  263. BUF_SIZE, &shared_heap_chain);
  264. /* app addr for shared heap */
  265. start1 = UINT32_MAX - 2 * BUF_SIZE + 1;
  266. end1 = UINT32_MAX - BUF_SIZE;
  267. start2 = UINT32_MAX - BUF_SIZE + 1;
  268. end2 = UINT32_MAX;
  269. /* shared heap 1 */
  270. argv[0] = end1;
  271. argv[1] = 101;
  272. test_shared_heap(shared_heap_chain, "test.wasm", "read_modify_write_8", 2,
  273. argv);
  274. EXPECT_EQ(0, argv[0]);
  275. EXPECT_EQ(preallocated_buf[BUF_SIZE - 1], 101);
  276. /* shared heap 2 */
  277. argv[0] = start2;
  278. argv[1] = 129;
  279. test_shared_heap(shared_heap_chain, "test.wasm", "read_modify_write_8", 2,
  280. argv);
  281. EXPECT_EQ(0, argv[0]);
  282. EXPECT_EQ(preallocated_buf2[0], 129);
  283. argv[0] = start1;
  284. argv[1] = 98;
  285. test_shared_heap(shared_heap_chain, "test_chain.aot", "read_modify_write_8",
  286. 2, argv);
  287. EXPECT_EQ(0, argv[0]);
  288. EXPECT_EQ(preallocated_buf[0], 98);
  289. argv[0] = end2;
  290. argv[1] = 81;
  291. test_shared_heap(shared_heap_chain, "test_chain.aot", "read_modify_write_8",
  292. 2, argv);
  293. EXPECT_EQ(0, argv[0]);
  294. EXPECT_EQ(preallocated_buf2[BUF_SIZE - 1], 81);
  295. }
  296. TEST_F(shared_heap_test, test_shared_heap_chain_rmw_bulk_memory)
  297. {
  298. SharedHeapInitArgs args = { 0 };
  299. WASMSharedHeap *shared_heap_chain = nullptr;
  300. uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize();
  301. uint8 preallocated_buf[BUF_SIZE] = { 0 },
  302. preallocated_buf2[BUF_SIZE] = { 0 };
  303. uint32 start1, end1, start2, end2;
  304. create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
  305. BUF_SIZE, &shared_heap_chain);
  306. /* app addr for shared heap */
  307. start1 = UINT32_MAX - 2 * BUF_SIZE + 1;
  308. end1 = UINT32_MAX - BUF_SIZE;
  309. start2 = UINT32_MAX - BUF_SIZE + 1;
  310. end2 = UINT32_MAX;
  311. argv[0] = end1;
  312. argv[1] = 101;
  313. argv[2] = 1;
  314. test_shared_heap(shared_heap_chain, "test_bulk_memory.wasm",
  315. "memory_fill_test", 3, argv);
  316. /* no modification since no return value */
  317. EXPECT_EQ(end1, argv[0]);
  318. EXPECT_EQ(preallocated_buf[BUF_SIZE - 1], 101);
  319. argv[0] = start1;
  320. argv[1] = 14;
  321. argv[2] = 1;
  322. test_shared_heap(shared_heap_chain, "test_bulk_memory_chain.aot",
  323. "memory_fill_test", 3, argv);
  324. /* no modification since no return value */
  325. EXPECT_EQ(start1, argv[0]);
  326. EXPECT_EQ(preallocated_buf[0], 14);
  327. /* nothing happen when memory fill 0 byte */
  328. argv[0] = start2;
  329. argv[1] = 68;
  330. argv[2] = 0;
  331. test_shared_heap(shared_heap_chain, "test_bulk_memory_chain.aot",
  332. "memory_fill_test", 3, argv);
  333. /* no modification since no return value */
  334. EXPECT_EQ(start2, argv[0]);
  335. EXPECT_EQ(preallocated_buf2[0], 0);
  336. argv[0] = end2;
  337. argv[1] = 98;
  338. argv[2] = 1;
  339. test_shared_heap(shared_heap_chain, "test_bulk_memory_chain.aot",
  340. "memory_fill_test", 3, argv);
  341. /* no modification since no return value */
  342. EXPECT_EQ(end2, argv[0]);
  343. EXPECT_EQ(preallocated_buf2[BUF_SIZE - 1], 98);
  344. }
  345. TEST_F(shared_heap_test, test_shared_heap_chain_rmw_bulk_memory_oob)
  346. {
  347. SharedHeapInitArgs args = { 0 };
  348. WASMSharedHeap *shared_heap_chain = nullptr;
  349. uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize();
  350. uint8 preallocated_buf[BUF_SIZE] = { 0 },
  351. preallocated_buf2[BUF_SIZE] = { 0 };
  352. uint32 start1, end1, start2, end2;
  353. create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
  354. BUF_SIZE, &shared_heap_chain);
  355. /* app addr for shared heap */
  356. start1 = UINT32_MAX - 2 * BUF_SIZE + 1;
  357. end1 = UINT32_MAX - BUF_SIZE;
  358. start2 = UINT32_MAX - BUF_SIZE + 1;
  359. end2 = UINT32_MAX;
  360. /* shared heap 1 */
  361. argv[0] = end1;
  362. argv[1] = 101;
  363. argv[2] = 2;
  364. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  365. "test_bulk_memory.wasm",
  366. "memory_fill_test", 3, argv),
  367. "Exception: out of bounds memory access");
  368. argv[0] = end2;
  369. argv[1] = 98;
  370. argv[2] = 2;
  371. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  372. "test_bulk_memory.wasm",
  373. "memory_fill_test", 3, argv),
  374. "Exception: out of bounds memory access");
  375. argv[0] = start1;
  376. argv[1] = 98;
  377. argv[2] = BUF_SIZE + 1;
  378. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  379. "test_bulk_memory.wasm",
  380. "memory_fill_test", 3, argv),
  381. "Exception: out of bounds memory access");
  382. argv[0] = start2;
  383. argv[1] = 98;
  384. argv[2] = BUF_SIZE + 1;
  385. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  386. "test_bulk_memory.wasm",
  387. "memory_fill_test", 3, argv),
  388. "Exception: out of bounds memory access");
  389. argv[0] = end1;
  390. argv[1] = 101;
  391. argv[2] = 2;
  392. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  393. "test_bulk_memory_chain.aot",
  394. "memory_fill_test", 3, argv),
  395. "Exception: out of bounds memory access");
  396. argv[0] = end2;
  397. argv[1] = 98;
  398. argv[2] = 2;
  399. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  400. "test_bulk_memory_chain.aot",
  401. "memory_fill_test", 3, argv),
  402. "Exception: out of bounds memory access");
  403. argv[0] = start1;
  404. argv[1] = 98;
  405. argv[2] = BUF_SIZE + 1;
  406. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  407. "test_bulk_memory_chain.aot",
  408. "memory_fill_test", 3, argv),
  409. "Exception: out of bounds memory access");
  410. argv[0] = start2;
  411. argv[1] = 98;
  412. argv[2] = BUF_SIZE + 1;
  413. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  414. "test_bulk_memory_chain.aot",
  415. "memory_fill_test", 3, argv),
  416. "Exception: out of bounds memory access");
  417. }
  418. TEST_F(shared_heap_test, test_shared_heap_rmw_oob)
  419. {
  420. WASMSharedHeap *shared_heap = nullptr;
  421. uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
  422. uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE];
  423. uint32 start1, end1, start2, end2;
  424. create_test_shared_heap(preallocated_buf, BUF_SIZE, &shared_heap);
  425. /* app addr for shared heap */
  426. start1 = UINT32_MAX - BUF_SIZE + 1;
  427. end1 = UINT32_MAX;
  428. /* try to rmw an u16, first u8 is in the first shared heap and second u8 is
  429. * in the second shared heap, will be seen as oob */
  430. argv[0] = end1;
  431. argv[1] = 12025;
  432. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test.wasm",
  433. "read_modify_write_16", 2, argv),
  434. "Exception: out of bounds memory access");
  435. argv[0] = start1 - 1;
  436. argv[1] = 12025;
  437. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test.aot",
  438. "read_modify_write_16", 2, argv),
  439. "Exception: out of bounds memory access");
  440. argv[0] = end1;
  441. argv[1] = 12025;
  442. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test.aot",
  443. "read_modify_write_16", 2, argv),
  444. "Exception: out of bounds memory access");
  445. }
  446. TEST_F(shared_heap_test, test_shared_heap_chain_rmw_oob)
  447. {
  448. WASMSharedHeap *shared_heap_chain = nullptr;
  449. uint32 argv[2] = { 0 }, BUF_SIZE = os_getpagesize();
  450. uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE];
  451. uint32 start1, end1, start2, end2;
  452. create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
  453. BUF_SIZE, &shared_heap_chain);
  454. /* app addr for shared heap */
  455. start1 = UINT32_MAX - 2 * BUF_SIZE + 1;
  456. end1 = UINT32_MAX - BUF_SIZE;
  457. start2 = UINT32_MAX - BUF_SIZE + 1;
  458. end2 = UINT32_MAX;
  459. /* try to rmw an u16, first u8 is in the first shared heap and second u8 is
  460. * in the second shared heap, will be seen as oob */
  461. argv[0] = end2;
  462. argv[1] = 12025;
  463. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain, "test.wasm",
  464. "read_modify_write_16", 2, argv),
  465. "Exception: out of bounds memory access");
  466. argv[0] = end1;
  467. argv[1] = 12025;
  468. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  469. "test_chain.aot",
  470. "read_modify_write_16", 2, argv),
  471. "Exception: out of bounds memory access");
  472. }
  473. #if WASM_ENABLE_MEMORY64 != 0
  474. TEST_F(shared_heap_test, test_shared_heap_chain_memory64_rmw)
  475. {
  476. WASMSharedHeap *shared_heap_chain = nullptr;
  477. uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize();
  478. uint8 preallocated_buf[BUF_SIZE] = { 0 },
  479. preallocated_buf2[BUF_SIZE] = { 0 };
  480. uint64 start1, end1, start2, end2;
  481. create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
  482. BUF_SIZE, &shared_heap_chain);
  483. /* app addr for shared heap */
  484. start1 = UINT64_MAX - 2 * BUF_SIZE + 1;
  485. end1 = UINT64_MAX - BUF_SIZE;
  486. start2 = UINT64_MAX - BUF_SIZE + 1;
  487. end2 = UINT64_MAX;
  488. /* shared heap 1 */
  489. PUT_I64_TO_ADDR(argv, end1);
  490. argv[2] = 101;
  491. test_shared_heap(shared_heap_chain, "test64.wasm", "read_modify_write_8", 3,
  492. argv);
  493. EXPECT_EQ(0, argv[0]);
  494. EXPECT_EQ(preallocated_buf[BUF_SIZE - 1], 101);
  495. /* shared heap 2 */
  496. PUT_I64_TO_ADDR(argv, start2);
  497. argv[2] = 129;
  498. test_shared_heap(shared_heap_chain, "test64.wasm", "read_modify_write_8", 3,
  499. argv);
  500. EXPECT_EQ(0, argv[0]);
  501. EXPECT_EQ(preallocated_buf2[0], 129);
  502. PUT_I64_TO_ADDR(argv, start1);
  503. argv[2] = 98;
  504. test_shared_heap(shared_heap_chain, "test64_chain.aot",
  505. "read_modify_write_8", 3, argv);
  506. EXPECT_EQ(0, argv[0]);
  507. EXPECT_EQ(preallocated_buf[0], 98);
  508. PUT_I64_TO_ADDR(argv, end2);
  509. argv[2] = 81;
  510. test_shared_heap(shared_heap_chain, "test64_chain.aot",
  511. "read_modify_write_8", 3, argv);
  512. EXPECT_EQ(0, argv[0]);
  513. EXPECT_EQ(preallocated_buf2[BUF_SIZE - 1], 81);
  514. }
  515. TEST_F(shared_heap_test, test_shared_heap_chain_memory64_rmw_oob)
  516. {
  517. WASMSharedHeap *shared_heap_chain = nullptr;
  518. uint32 argv[3] = { 0 }, BUF_SIZE = os_getpagesize();
  519. uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE];
  520. uint64 start1, end1, start2, end2;
  521. create_test_shared_heap_chain(preallocated_buf, BUF_SIZE, preallocated_buf2,
  522. BUF_SIZE, &shared_heap_chain);
  523. /* app addr for shared heap */
  524. start1 = UINT64_MAX - 2 * BUF_SIZE + 1;
  525. end1 = UINT64_MAX - BUF_SIZE;
  526. start2 = UINT64_MAX - BUF_SIZE + 1;
  527. end2 = UINT64_MAX;
  528. /* try to rmw an u16, first u8 is in the first shared heap and second u8 is
  529. * in the second shared heap, will be seen as oob */
  530. PUT_I64_TO_ADDR(argv, end1);
  531. argv[2] = 12025;
  532. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain, "test64.wasm",
  533. "read_modify_write_16", 3, argv),
  534. "Exception: out of bounds memory access");
  535. PUT_I64_TO_ADDR(argv, end1);
  536. argv[2] = 12025;
  537. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  538. "test64_chain.aot",
  539. "read_modify_write_16", 3, argv),
  540. "Exception: out of bounds memory access");
  541. }
  542. #endif
  543. #ifndef native_function
  544. /* clang-format off */
  545. #define native_function(func_name, signature) \
  546. { #func_name, (void *)glue_## func_name, signature, NULL }
  547. /* clang-format on */
  548. #endif
  549. #ifndef nitems
  550. #define nitems(_a) (sizeof(_a) / sizeof(0 [(_a)]))
  551. #endif /* nitems */
  552. uintptr_t
  553. glue_test_addr_conv(wasm_exec_env_t env, uintptr_t addr)
  554. {
  555. wasm_module_inst_t module_inst = get_module_inst(env);
  556. void *native_addr = (void *)addr;
  557. uintptr_t app_addr = addr_native_to_app(native_addr);
  558. native_addr = addr_app_to_native(app_addr);
  559. if (native_addr != (void *)addr) {
  560. ADD_FAILURE() << "address conversion incorrect";
  561. return 0;
  562. }
  563. return app_addr;
  564. }
  565. static NativeSymbol g_test_native_symbols[] = {
  566. native_function(test_addr_conv, "(*)i"),
  567. };
  568. TEST_F(shared_heap_test, test_addr_conv)
  569. {
  570. SharedHeapInitArgs args = { 0 };
  571. WASMSharedHeap *shared_heap = nullptr;
  572. uint32 argv[1] = { 0 };
  573. bool ret = false;
  574. ret = wasm_native_register_natives("env", g_test_native_symbols,
  575. nitems(g_test_native_symbols));
  576. if (!ret) {
  577. FAIL() << "Failed to register natives";
  578. }
  579. args.size = 1024;
  580. shared_heap = wasm_runtime_create_shared_heap(&args);
  581. if (!shared_heap) {
  582. FAIL() << "Failed to create shared heap";
  583. }
  584. test_shared_heap(shared_heap, "test_addr_conv.wasm", "test", 0, argv);
  585. EXPECT_EQ(1, argv[0]);
  586. test_shared_heap(shared_heap, "test_addr_conv.aot", "test", 0, argv);
  587. EXPECT_EQ(1, argv[0]);
  588. test_shared_heap(shared_heap, "test_addr_conv_chain.aot", "test", 0, argv);
  589. EXPECT_EQ(1, argv[0]);
  590. }
  591. TEST_F(shared_heap_test, test_addr_conv_pre_allocated_oob)
  592. {
  593. SharedHeapInitArgs args = { 0 };
  594. WASMSharedHeap *shared_heap = nullptr;
  595. uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize(),
  596. app_addr = 0xFFFFFFFF - BUF_SIZE;
  597. uint8 preallocated_buf[BUF_SIZE];
  598. bool ret = false;
  599. /* create a preallocated shared heap */
  600. ret = wasm_native_register_natives("env", g_test_native_symbols,
  601. nitems(g_test_native_symbols));
  602. if (!ret) {
  603. FAIL() << "Failed to register natives";
  604. }
  605. args.pre_allocated_addr = preallocated_buf;
  606. args.size = BUF_SIZE;
  607. shared_heap = wasm_runtime_create_shared_heap(&args);
  608. if (!shared_heap) {
  609. FAIL() << "Failed to create shared heap";
  610. }
  611. argv[0] = app_addr;
  612. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test_addr_conv.wasm",
  613. "test_preallocated", 1, argv),
  614. "Exception: out of bounds memory access");
  615. argv[0] = app_addr;
  616. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap, "test_addr_conv.aot",
  617. "test_preallocated", 1, argv),
  618. "Exception: out of bounds memory access");
  619. argv[0] = app_addr;
  620. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap,
  621. "test_addr_conv_chain.aot",
  622. "test_preallocated", 1, argv),
  623. "Exception: out of bounds memory access");
  624. }
  625. TEST_F(shared_heap_test, test_shared_heap_chain)
  626. {
  627. SharedHeapInitArgs args = { 0 };
  628. WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr,
  629. *shared_heap_chain = nullptr;
  630. uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize();
  631. uint8 preallocated_buf[BUF_SIZE];
  632. bool ret = false;
  633. ret = wasm_native_register_natives("env", g_test_native_symbols,
  634. nitems(g_test_native_symbols));
  635. if (!ret) {
  636. FAIL() << "Failed to register natives";
  637. }
  638. args.size = 1024;
  639. shared_heap = wasm_runtime_create_shared_heap(&args);
  640. if (!shared_heap) {
  641. FAIL() << "Failed to create shared heap";
  642. }
  643. /* create a preallocated shared heap */
  644. memset(&args, 0, sizeof(args));
  645. args.pre_allocated_addr = preallocated_buf;
  646. args.size = BUF_SIZE;
  647. shared_heap2 = wasm_runtime_create_shared_heap(&args);
  648. if (!shared_heap2) {
  649. FAIL() << "Create preallocated shared heap failed.\n";
  650. }
  651. shared_heap_chain =
  652. wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
  653. if (!shared_heap_chain) {
  654. FAIL() << "Create shared heap chain failed.\n";
  655. }
  656. test_shared_heap(shared_heap_chain, "test_addr_conv.wasm", "test", 0, argv);
  657. EXPECT_EQ(1, argv[0]);
  658. test_shared_heap(shared_heap, "test_addr_conv.aot", "test", 0, argv);
  659. EXPECT_EQ(1, argv[0]);
  660. }
  661. TEST_F(shared_heap_test, test_shared_heap_chain_create_fail)
  662. {
  663. SharedHeapInitArgs args = { 0 };
  664. WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr,
  665. *shared_heap_chain = nullptr;
  666. args.size = 1024;
  667. shared_heap = wasm_runtime_create_shared_heap(&args);
  668. if (!shared_heap) {
  669. FAIL() << "Failed to create shared heap";
  670. }
  671. args.size = 4096;
  672. shared_heap2 = wasm_runtime_create_shared_heap(&args);
  673. if (!shared_heap2) {
  674. FAIL() << "Create preallocated shared heap failed.\n";
  675. }
  676. shared_heap_chain =
  677. wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
  678. EXPECT_EQ(shared_heap_chain, nullptr);
  679. }
  680. TEST_F(shared_heap_test, test_shared_heap_chain_create_fail2)
  681. {
  682. SharedHeapInitArgs args = { 0 };
  683. WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr,
  684. *shared_heap_chain = nullptr;
  685. uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize();
  686. uint8 preallocated_buf[BUF_SIZE];
  687. struct ret_env tmp_module_env;
  688. args.size = 1024;
  689. shared_heap = wasm_runtime_create_shared_heap(&args);
  690. if (!shared_heap) {
  691. FAIL() << "Failed to create shared heap";
  692. }
  693. memset(&args, 0, sizeof(args));
  694. args.pre_allocated_addr = preallocated_buf;
  695. args.size = BUF_SIZE;
  696. shared_heap2 = wasm_runtime_create_shared_heap(&args);
  697. if (!shared_heap2) {
  698. FAIL() << "Create preallocated shared heap failed.\n";
  699. }
  700. if (!load_wasm((char *)"test.wasm", 0, tmp_module_env)) {
  701. FAIL() << "Failed to load wasm file\n";
  702. }
  703. if (!wasm_runtime_attach_shared_heap(tmp_module_env.wasm_module_inst,
  704. shared_heap)) {
  705. FAIL() << "Failed to attach shared heap\n";
  706. }
  707. /* can't create shared heap chain when shared heap is attached to a wasm
  708. * app */
  709. shared_heap_chain =
  710. wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
  711. EXPECT_EQ(shared_heap_chain, nullptr);
  712. wasm_runtime_detach_shared_heap(tmp_module_env.wasm_module_inst);
  713. destroy_module_env(tmp_module_env);
  714. }
  715. TEST_F(shared_heap_test, test_shared_heap_chain_create_fail3)
  716. {
  717. SharedHeapInitArgs args = { 0 };
  718. WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr,
  719. *shared_heap3 = nullptr, *shared_heap_chain = nullptr;
  720. uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize();
  721. uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE];
  722. args.size = 1024;
  723. shared_heap = wasm_runtime_create_shared_heap(&args);
  724. if (!shared_heap) {
  725. FAIL() << "Failed to create shared heap";
  726. }
  727. memset(&args, 0, sizeof(args));
  728. args.pre_allocated_addr = preallocated_buf;
  729. args.size = BUF_SIZE;
  730. shared_heap2 = wasm_runtime_create_shared_heap(&args);
  731. if (!shared_heap2) {
  732. FAIL() << "Create preallocated shared heap failed.\n";
  733. }
  734. shared_heap_chain =
  735. wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
  736. if (!shared_heap_chain) {
  737. FAIL() << "Create shared heap chain failed.\n";
  738. }
  739. memset(&args, 0, sizeof(args));
  740. args.pre_allocated_addr = preallocated_buf2;
  741. args.size = BUF_SIZE;
  742. shared_heap3 = wasm_runtime_create_shared_heap(&args);
  743. if (!shared_heap3) {
  744. FAIL() << "Failed to create shared heap";
  745. }
  746. /* The head and body can't be already in other shared heap chain as body */
  747. shared_heap_chain =
  748. wasm_runtime_chain_shared_heaps(shared_heap3, shared_heap2);
  749. EXPECT_EQ(shared_heap_chain, nullptr);
  750. shared_heap_chain =
  751. wasm_runtime_chain_shared_heaps(shared_heap2, shared_heap);
  752. EXPECT_EQ(shared_heap_chain, nullptr);
  753. }
  754. TEST_F(shared_heap_test, test_shared_heap_chain_unchain)
  755. {
  756. SharedHeapInitArgs args = { 0 };
  757. WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr,
  758. *shared_heap3 = nullptr, *shared_heap_chain = nullptr;
  759. uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize();
  760. uint8 preallocated_buf[BUF_SIZE], preallocated_buf2[BUF_SIZE];
  761. args.size = 1024;
  762. shared_heap = wasm_runtime_create_shared_heap(&args);
  763. if (!shared_heap) {
  764. FAIL() << "Failed to create shared heap";
  765. }
  766. memset(&args, 0, sizeof(args));
  767. args.pre_allocated_addr = preallocated_buf;
  768. args.size = BUF_SIZE;
  769. shared_heap2 = wasm_runtime_create_shared_heap(&args);
  770. if (!shared_heap2) {
  771. FAIL() << "Create preallocated shared heap failed.\n";
  772. }
  773. shared_heap_chain =
  774. wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
  775. if (!shared_heap_chain) {
  776. FAIL() << "Create shared heap chain failed.\n";
  777. }
  778. memset(&args, 0, sizeof(args));
  779. args.pre_allocated_addr = preallocated_buf2;
  780. args.size = BUF_SIZE;
  781. shared_heap3 = wasm_runtime_create_shared_heap(&args);
  782. if (!shared_heap3) {
  783. FAIL() << "Failed to create shared heap";
  784. }
  785. /* unchain shared heap so that the 'body' can be another chain 'body'
  786. * again(1->2 to 1->3->2) */
  787. EXPECT_EQ(shared_heap2,
  788. wasm_runtime_unchain_shared_heaps(shared_heap_chain, false));
  789. shared_heap_chain =
  790. wasm_runtime_chain_shared_heaps(shared_heap3, shared_heap2);
  791. EXPECT_EQ(shared_heap_chain, shared_heap3);
  792. shared_heap_chain =
  793. wasm_runtime_chain_shared_heaps(shared_heap, shared_heap3);
  794. EXPECT_EQ(shared_heap, shared_heap_chain);
  795. /* break down the entire shared heap chain */
  796. EXPECT_EQ(shared_heap2,
  797. wasm_runtime_unchain_shared_heaps(shared_heap_chain, true));
  798. }
  799. TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv)
  800. {
  801. SharedHeapInitArgs args = { 0 };
  802. WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr,
  803. *shared_heap_chain = nullptr;
  804. uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize();
  805. uint8 preallocated_buf[BUF_SIZE];
  806. bool ret = false;
  807. ret = wasm_native_register_natives("env", g_test_native_symbols,
  808. nitems(g_test_native_symbols));
  809. if (!ret) {
  810. FAIL() << "Failed to register natives";
  811. }
  812. args.size = 4096;
  813. shared_heap = wasm_runtime_create_shared_heap(&args);
  814. if (!shared_heap) {
  815. FAIL() << "Failed to create shared heap";
  816. }
  817. /* create a preallocated shared heap */
  818. memset(&args, 0, sizeof(args));
  819. args.pre_allocated_addr = preallocated_buf;
  820. args.size = BUF_SIZE;
  821. shared_heap2 = wasm_runtime_create_shared_heap(&args);
  822. if (!shared_heap2) {
  823. FAIL() << "Create preallocated shared heap failed.\n";
  824. }
  825. shared_heap_chain =
  826. wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
  827. if (!shared_heap_chain) {
  828. FAIL() << "Create shared heap chain failed.\n";
  829. }
  830. argv[0] = 0xFFFFFFFF;
  831. test_shared_heap(shared_heap_chain, "test_addr_conv.wasm",
  832. "test_preallocated", 1, argv);
  833. EXPECT_EQ(1, argv[0]);
  834. argv[0] = 0xFFFFF000;
  835. test_shared_heap(shared_heap_chain, "test_addr_conv.wasm",
  836. "test_preallocated", 1, argv);
  837. EXPECT_EQ(1, argv[0]);
  838. argv[0] = 0xFFFFFFFF;
  839. test_shared_heap(shared_heap, "test_addr_conv_chain.aot",
  840. "test_preallocated", 1, argv);
  841. EXPECT_EQ(1, argv[0]);
  842. argv[0] = 0xFFFFF000;
  843. test_shared_heap(shared_heap, "test_addr_conv_chain.aot",
  844. "test_preallocated", 1, argv);
  845. EXPECT_EQ(1, argv[0]);
  846. }
  847. TEST_F(shared_heap_test, test_shared_heap_chain_addr_conv_oob)
  848. {
  849. SharedHeapInitArgs args = { 0 };
  850. WASMSharedHeap *shared_heap = nullptr, *shared_heap2 = nullptr,
  851. *shared_heap_chain = nullptr;
  852. uint32 argv[1] = { 0 }, BUF_SIZE = os_getpagesize();
  853. uint8 preallocated_buf[BUF_SIZE];
  854. bool ret = false;
  855. ret = wasm_native_register_natives("env", g_test_native_symbols,
  856. nitems(g_test_native_symbols));
  857. if (!ret) {
  858. FAIL() << "Failed to register natives";
  859. }
  860. args.size = 4096;
  861. shared_heap = wasm_runtime_create_shared_heap(&args);
  862. if (!shared_heap) {
  863. FAIL() << "Failed to create shared heap";
  864. }
  865. /* create a preallocated shared heap */
  866. memset(&args, 0, sizeof(args));
  867. args.pre_allocated_addr = preallocated_buf;
  868. args.size = BUF_SIZE;
  869. shared_heap2 = wasm_runtime_create_shared_heap(&args);
  870. if (!shared_heap2) {
  871. FAIL() << "Create preallocated shared heap failed.\n";
  872. }
  873. shared_heap_chain =
  874. wasm_runtime_chain_shared_heaps(shared_heap, shared_heap2);
  875. if (!shared_heap_chain) {
  876. FAIL() << "Create shared heap chain failed.\n";
  877. }
  878. /* test wasm */
  879. argv[0] = 0xFFFFFFFF - BUF_SIZE - 4096;
  880. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  881. "test_addr_conv.wasm",
  882. "test_preallocated", 1, argv),
  883. "Exception: out of bounds memory access");
  884. /* test aot */
  885. argv[0] = 0xFFFFFFFF - BUF_SIZE - 4096;
  886. EXPECT_NONFATAL_FAILURE(test_shared_heap(shared_heap_chain,
  887. "test_addr_conv_chain.aot",
  888. "test_preallocated", 1, argv),
  889. "Exception: out of bounds memory access");
  890. }