PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/TestStackRealloc.cpp

https://code.google.com/p/nullc/
C++ | 523 lines | 490 code | 33 blank | 0 comment | 8 complexity | ed1b2731c5f1efc0f3a4f2309b20eb91 MD5 | raw file
  1. #include "TestBase.h"
  2. #if defined(_MSC_VER)
  3. #pragma warning(disable: 4530)
  4. #include "../stdafx.h"
  5. #endif
  6. #include "../NULLC/includes/file.h"
  7. #include "../NULLC/includes/math.h"
  8. #include "../NULLC/includes/vector.h"
  9. #include "../NULLC/includes/random.h"
  10. #include "../NULLC/includes/dynamic.h"
  11. #include "../NULLC/includes/gc.h"
  12. #include "../NULLC/includes/time.h"
  13. #include "../NULLC/includes/canvas.h"
  14. #include "../NULLC/includes/window.h"
  15. #include "../NULLC/includes/io.h"
  16. #include "../NULLC/includes/pugi.h"
  17. const char *testStackResize =
  18. "class RefHold\r\n\
  19. {\r\n\
  20. int ref c;\r\n\
  21. }\r\n\
  22. int a = 12;\r\n\
  23. int ref b = &a;\r\n\
  24. auto h = new RefHold;\r\n\
  25. h.c = b;\r\n\
  26. auto ref c = &a;\r\n\
  27. int ref[2] d;\r\n\
  28. int ref[] e = d, e0;\r\n\
  29. int[2][2] u;\r\n\
  30. RefHold[] u2 = { *h, *h, *h };\r\n\
  31. e[0] = &a;\r\n\
  32. auto func()\r\n\
  33. {\r\n\
  34. auto f2()\r\n\
  35. {\r\n\
  36. int[4096] arr;\r\n\
  37. }\r\n\
  38. f2();\r\n\
  39. return b;\r\n\
  40. }\r\n\
  41. int ref res = func();\r\n\
  42. int ref v = c;\r\n\
  43. a = 10;\r\n\
  44. return *res + *h.c + *v + *e[0];";
  45. TEST_RELOCATE("Parameter stack resize", testStackResize, "40");
  46. const char *testStackRelocationFrameSizeX64 =
  47. "int a = 1;\r\n\
  48. void test()\r\n\
  49. {\r\n\
  50. int[1024*1024] e = 0;\r\n\
  51. a = 6;\r\n\
  52. }\r\n\
  53. void help()\r\n\
  54. {\r\n\
  55. auto e = &a;\r\n\
  56. test();\r\n\
  57. assert(*e == a);\r\n\
  58. assert(*e == 6);\r\n\
  59. }\r\n\
  60. void help2(int a_, b, c)\r\n\
  61. {\r\n\
  62. help();\r\n\
  63. }\r\n\
  64. help2(2, 3, 4);\r\n\
  65. return 0;";
  66. TEST_RELOCATE("Stack frame size calculation in VM stack relocation under x64", testStackRelocationFrameSizeX64, "0");
  67. const char *testStackRelocationFrameSizeX86 =
  68. "int a = 1;\r\n\
  69. void test()\r\n\
  70. {\r\n\
  71. int[1024*1024] e = 0;\r\n\
  72. a = 6;\r\n\
  73. }\r\n\
  74. void help()\r\n\
  75. {\r\n\
  76. auto e = &a;\r\n\
  77. test();\r\n\
  78. assert(*e == a);\r\n\
  79. assert(*e == 6);\r\n\
  80. }\r\n\
  81. void help2(int a_, b, c, d)\r\n\
  82. {\r\n\
  83. help();\r\n\
  84. }\r\n\
  85. help2(2, 3, 4, 5);\r\n\
  86. return 0;";
  87. TEST_RELOCATE("Stack frame size calculation in VM stack relocation under x86", testStackRelocationFrameSizeX86, "0");
  88. const char *testStackRelocationFrameSizeX64_2 =
  89. "int a = 1;\r\n\
  90. void corrupt()\r\n\
  91. {\r\n\
  92. int[1024*1024] e = 0;\r\n\
  93. a = 6;\r\n\
  94. }\r\n\
  95. void test()\r\n\
  96. {\r\n\
  97. auto e = &a;\r\n\
  98. corrupt();\r\n\
  99. assert(*e == a);\r\n\
  100. assert(*e == 6);\r\n\
  101. }\r\n\
  102. auto rurr()\r\n\
  103. {\r\n\
  104. // function local state (x64):\r\n\
  105. // $context at base + 0 (sizeof 8)\r\n\
  106. // d at base + 8 (sizeof 4)\r\n\
  107. // pad at base + 12 (sizeof 4)\r\n\
  108. // b1 at base + 24 (sizeof 12)\r\n\
  109. // $lamda_27_ext at base + 16 (sizeof 8)\r\n\
  110. // stack frame end is at 36, but incorrect calculation will return 24\r\n\
  111. // stack frame alignment will translate this to 48 and 32, creating an error\r\n\
  112. int d = 5;\r\n\
  113. int pad = 8;\r\n\
  114. auto b1 = int lambda(int b){ return b + d; };\r\n\
  115. test();\r\n\
  116. d = 7;\r\n\
  117. return b1(4);\r\n\
  118. }\r\n\
  119. return rurr();";
  120. TEST_RELOCATE("Stack frame size calculation in VM stack relocation under x64 2", testStackRelocationFrameSizeX64_2, "11");
  121. const char *testStackRelocationFrameSizeX86_2 =
  122. "int a = 1;\r\n\
  123. void corrupt()\r\n\
  124. {\r\n\
  125. int[1024*1024] e = 0;\r\n\
  126. a = 6;\r\n\
  127. }\r\n\
  128. void test()\r\n\
  129. {\r\n\
  130. auto e = &a;\r\n\
  131. corrupt();\r\n\
  132. assert(*e == a);\r\n\
  133. assert(*e == 6);\r\n\
  134. }\r\n\
  135. auto rurr()\r\n\
  136. {\r\n\
  137. // function local state (x86):\r\n\
  138. // $context at base + 0 (sizeof 4)\r\n\
  139. // d at base + 4 (sizeof 4)\r\n\
  140. // b1 at base + 12 (sizeof 8)\r\n\
  141. // $lamda_27_ext at base + 8 (sizeof 4)\r\n\
  142. // stack frame end is at 20, but incorrect calculation will return 12\r\n\
  143. // stack frame alignment will translate this to 32 and 16, creating an error\r\n\
  144. int d = 5;\r\n\
  145. auto b1 = int lambda(int b){ return b + d; };\r\n\
  146. test();\r\n\
  147. d = 7;\r\n\
  148. return b1(4);\r\n\
  149. }\r\n\
  150. return rurr();";
  151. TEST_RELOCATE("Stack frame size calculation in VM stack relocation under x86 2", testStackRelocationFrameSizeX86_2, "11");
  152. const char *testStackRelocationFunction =
  153. "class A\r\n\
  154. {\r\n\
  155. int x, y;\r\n\
  156. int sum(){ return x + y; }\r\n\
  157. }\r\n\
  158. A a;\r\n\
  159. a.x = 1;\r\n\
  160. a.y = 2;\r\n\
  161. auto f = a.sum;\r\n\
  162. void corrupt()\r\n\
  163. {\r\n\
  164. int[32*1024] e = 0;\r\n\
  165. }\r\n\
  166. corrupt();\r\n\
  167. a.x = 4;\r\n\
  168. a.y = 9;\r\n\
  169. return f();";
  170. TEST_RELOCATE("VM stack relocation function check", testStackRelocationFunction, "13");
  171. const char *testStackRelocationFunction2 =
  172. "void corrupt()\r\n\
  173. {\r\n\
  174. int[32*1024] e = 0;\r\n\
  175. }\r\n\
  176. auto foo()\r\n\
  177. {\r\n\
  178. int i = 3;\r\n\
  179. auto help()\r\n\
  180. {\r\n\
  181. int ref func()\r\n\
  182. {\r\n\
  183. return &i;\r\n\
  184. }\r\n\
  185. return func;\r\n\
  186. }\r\n\
  187. auto f = help();\r\n\
  188. corrupt();\r\n\
  189. i = 8;\r\n\
  190. int ref data = f();\r\n\
  191. return *data;\r\n\
  192. }\r\n\
  193. return foo();";
  194. TEST_RELOCATE("VM stack relocation function check 2", testStackRelocationFunction2, "8");
  195. const char *testStackRelocationFunction3 =
  196. "void corrupt()\r\n\
  197. {\r\n\
  198. int[32*1024] e = 0;\r\n\
  199. }\r\n\
  200. auto foo()\r\n\
  201. {\r\n\
  202. int i = 3;\r\n\
  203. auto help()\r\n\
  204. {\r\n\
  205. int ref func()\r\n\
  206. {\r\n\
  207. return &i;\r\n\
  208. }\r\n\
  209. return func;\r\n\
  210. }\r\n\
  211. int ref ref()[1] f;\r\n\
  212. f[0] = help();\r\n\
  213. corrupt();\r\n\
  214. i = 8;\r\n\
  215. int ref data = f[0]();\r\n\
  216. return *data;\r\n\
  217. }\r\n\
  218. return foo();";
  219. TEST_RELOCATE("VM stack relocation function check 3", testStackRelocationFunction3, "8");
  220. const char *testVMRelocateArrayFail =
  221. "class Foo{ Foo[] arr; int x; }\r\n\
  222. Foo[2] fuck;\r\n\
  223. fuck[0].x = 2;\r\n\
  224. fuck[1].x = 5;\r\n\
  225. Foo[] x = fuck;\r\n\
  226. Foo y;\r\n\
  227. y.arr = x;\r\n\
  228. x[0] = y;\r\n\
  229. void corrupt()\r\n\
  230. {\r\n\
  231. int[1024*1024] e = 0;\r\n\
  232. }\r\n\
  233. corrupt();\r\n\
  234. fuck[0].x = 12;\r\n\
  235. fuck[1].x = 25;\r\n\
  236. return x[0].x + x[1].x;";
  237. TEST_RELOCATE("VM stack relocation test with possible infinite recursion", testVMRelocateArrayFail, "37");
  238. const char *testVMRelocateArrayFail2 =
  239. "class Foo{ Foo[] arr; int x; }\r\n\
  240. Foo[] x = new Foo[2];\r\n\
  241. x[0].x = 2;\r\n\
  242. x[1].x = 5;\r\n\
  243. Foo y;\r\n\
  244. y.arr = x;\r\n\
  245. x[0] = y;\r\n\
  246. void corrupt()\r\n\
  247. {\r\n\
  248. int[1024*1024] e = 0;\r\n\
  249. }\r\n\
  250. corrupt();\r\n\
  251. x[0].x = 12;\r\n\
  252. x[1].x = 25;\r\n\
  253. return x[0].x + x[1].x;";
  254. TEST_RELOCATE("VM stack relocation test with possible infinite recursion 2", testVMRelocateArrayFail2, "37");
  255. const char *testStackRelocationClassAlignedMembers =
  256. "void corrupt()\r\n\
  257. {\r\n\
  258. int[32*1024] e = 0;\r\n\
  259. }\r\n\
  260. int z = 5;\r\n\
  261. class Test{ char a; int c; int ref b; }\r\n\
  262. Test x;\r\n\
  263. x.a = 5;\r\n\
  264. x.b = &z;\r\n\
  265. corrupt();\r\n\
  266. z = 15;\r\n\
  267. return *x.b;";
  268. TEST_RELOCATE("VM stack relocation with aligned class members", testStackRelocationClassAlignedMembers, "15");
  269. const char *testAutoArrayRelocation =
  270. "import old.vector;\r\n\
  271. \r\n\
  272. class A\r\n\
  273. {\r\n\
  274. int ref a, b;\r\n\
  275. }\r\n\
  276. int av = 7, bv = 30;\r\n\
  277. vector arr = vector(A);\r\n\
  278. auto test = new A;\r\n\
  279. test.a = &av;\r\n\
  280. test.b = &bv;\r\n\
  281. arr.push_back(test);\r\n\
  282. test = nullptr;\r\n\
  283. void corrupt()\r\n\
  284. {\r\n\
  285. int[32*1024] e = 0;\r\n\
  286. }\r\n\
  287. corrupt();\r\n\
  288. test = arr.back();\r\n\
  289. av = 4;\r\n\
  290. bv = 60;\r\n\
  291. return *test.a + *test.b;";
  292. TEST_RELOCATE("VM stack relocation (auto[] type)", testAutoArrayRelocation, "64");
  293. const char *testAutoArrayRelocation2 =
  294. "import old.vector;\r\n\
  295. vector arr = vector(int);\r\n\
  296. void corrupt()\r\n\
  297. {\r\n\
  298. int[32*1024] e = 0;\r\n\
  299. }\r\n\
  300. corrupt();\r\n\
  301. return 1;";
  302. TEST_RELOCATE("VM stack relocation (uninitialized auto[] type)", testAutoArrayRelocation2, "1");
  303. const char *testAutoArrayRelocation3 =
  304. "auto[] arr = { 1, 20, 300 };\r\n\
  305. void corrupt()\r\n\
  306. {\r\n\
  307. int[32*1024] e = 0;\r\n\
  308. }\r\n\
  309. corrupt();\r\n\
  310. return int(arr[0]) + int(arr[1]) + int(arr[2]);";
  311. TEST_RELOCATE("VM stack relocation (auto[] data on stack)", testAutoArrayRelocation3, "321");
  312. const char *testAutoRefRecursionRelocate =
  313. "auto ref y = &y;\r\n\
  314. void corrupt()\r\n\
  315. {\r\n\
  316. int[32*1024] e = 0;\r\n\
  317. }\r\n\
  318. corrupt();\r\n\
  319. return 1;";
  320. TEST_RELOCATE("VM stack relocation (auto ref recursion)", testAutoRefRecursionRelocate, "1");
  321. const char *testExtraArgumentRelocate =
  322. "class Test{ int x; }\r\n\
  323. int ref Test:getX(){ int[32*1024] make_stack_reallocation; return &x; }\r\n\
  324. Test a;\r\n\
  325. a.x = 5;\r\n\
  326. auto y = a.getX();\r\n\
  327. a.x = 8;\r\n\
  328. return *y;";
  329. TEST_RELOCATE("VM stack relocation (extra function argument)", testExtraArgumentRelocate, "8");
  330. const char *testCoroutineNoLocalStackRelocate =
  331. "void fuckup(){ int[128] i = 0xfeeefeee; } fuckup();\r\n\
  332. void corrupt(){ int[32*1024] e = 0; }\r\n\
  333. coroutine auto test()\r\n\
  334. {\r\n\
  335. auto ref x, y, z, w, k, l, m; int i = 3;\r\n\
  336. corrupt();\r\n\
  337. yield 2; return 3;\r\n\
  338. }\r\n\
  339. test(); return test();";
  340. TEST_RELOCATE("VM stack relocation (coroutine without stack for locals)", testCoroutineNoLocalStackRelocate, "3");
  341. const char *testAutoRefStackRelocate =
  342. "class Foo{ int ref y; }\r\n\
  343. int x = 4;\r\n\
  344. auto y = new Foo;\r\n\
  345. y.y = &x;\r\n\
  346. auto ref z = y, w = z;\r\n\
  347. y = nullptr;\r\n\
  348. void corrupt(){ int[32*1024] e = 0xfeeefeee; } corrupt();\r\n\
  349. x = 8;\r\n\
  350. return *Foo(z).y;";
  351. TEST_RELOCATE("VM stack relocation (auto ref)", testAutoRefStackRelocate, "8");
  352. const char *testArrayOfArraysStackRelocate =
  353. "class Foo{ int ref y; }\r\n\
  354. Foo[1][4] arr;\r\n\
  355. int x = 1, y = 1, z = 1, w = 1;\r\n\
  356. arr[0][0].y = &x; arr[0][1].y = &y; arr[0][2].y = &z; arr[0][3].y = &w;\r\n\
  357. void corrupt(){ int[32*1024] e = 0; } corrupt();\r\n\
  358. x = 2; y = 30; z = 400; w = 5000;\r\n\
  359. return *arr[0][0].y + *arr[0][1].y + *arr[0][2].y + *arr[0][3].y;";
  360. TEST_RELOCATE("VM stack relocation (array of arrays)", testArrayOfArraysStackRelocate, "5432");
  361. const char *testCorrectStackRelocate =
  362. "void garbage(){ int[768] arr; for(i in arr) i = 0xdeadbeef; }\r\n\
  363. void victim(){ auto ref[768] arr; }\r\n\
  364. garbage();\r\n\
  365. victim();\r\n\
  366. return 1;";
  367. TEST_RELOCATE("VM stack relocation (correct stack clear)", testCorrectStackRelocate, "1");
  368. struct TestEval : TestQueue
  369. {
  370. virtual void Run()
  371. {
  372. nullcTerminate();
  373. nullcInit(MODULE_PATH);
  374. nullcInitDynamicModule();
  375. const char *testEval =
  376. "import std.dynamic;\r\n\
  377. \r\n\
  378. int a = 5;\r\n\
  379. \r\n\
  380. for(int i = 0; i < 200; i++)\r\n\
  381. eval(\"a += 3 * \" + i.str() + \";\");\r\n\
  382. \r\n\
  383. return a;";
  384. double evalStart = myGetPreciseTime();
  385. for(unsigned t = 0; t < 2; t++)
  386. {
  387. if(!Tests::testExecutor[t])
  388. continue;
  389. testsCount[t]++;
  390. if(Tests::RunCode(testEval, t, "59705", "Dynamic code. eval()"))
  391. testsPassed[t]++;
  392. printf("Eval test finished in %f\r\n", myGetPreciseTime() - evalStart);
  393. }
  394. nullcTerminate();
  395. nullcInit(MODULE_PATH);
  396. nullcInitDynamicModule();
  397. }
  398. };
  399. TestEval testEval;
  400. const char *testCoroutineAndEval =
  401. "import std.dynamic;\r\n\
  402. coroutine int foo()\r\n\
  403. {\r\n\
  404. int i = 0;\r\n\
  405. yield i++;\r\n\
  406. yield i++;\r\n\
  407. yield i++;\r\n\
  408. return i;\r\n\
  409. }\r\n\
  410. foo();\r\n\
  411. int x = foo();\r\n\
  412. int a = 5;\r\n\
  413. \r\n\
  414. for(int i = 0; i < 200; i++)\r\n\
  415. eval(\"a = 3 * \" + i.str() + \";\");\r\n\
  416. int y = foo();\r\n\
  417. return x * 10 + y;";
  418. TEST("Coroutine and dynamic code. eval()", testCoroutineAndEval, "12")
  419. {
  420. }
  421. struct TestVariableImportCorrectness : TestQueue
  422. {
  423. virtual void Run()
  424. {
  425. nullcTerminate();
  426. nullcInit(MODULE_PATH);
  427. nullcInitDynamicModule();
  428. const char *testVariableImportCorrectness =
  429. "import std.dynamic;\r\n\
  430. int x = 2;\r\n\
  431. eval(\"x = 4;\");\r\n\
  432. { int n, m; }\r\n\
  433. int y = 3;\r\n\
  434. eval(\"y = 8;\");\r\n\
  435. return x * 10 + y;";
  436. for(unsigned t = 0; t < 2; t++)
  437. {
  438. if(!Tests::testExecutor[t])
  439. continue;
  440. testsCount[t]++;
  441. if(Tests::RunCode(testVariableImportCorrectness, t, "48", "Variable import correctness"))
  442. testsPassed[t]++;
  443. }
  444. }
  445. };
  446. TestVariableImportCorrectness testVariableImportCorrectness;
  447. struct TestGCGlobalLimit : TestQueue
  448. {
  449. virtual void Run()
  450. {
  451. nullcTerminate();
  452. nullcInit(MODULE_PATH);
  453. nullcInitGCModule();
  454. nullcSetGlobalMemoryLimit(1024 * 1024);
  455. const char *testGCGlobalLimit =
  456. "import std.gc;\r\n\
  457. int[] arr1 = new int[200000];\r\n\
  458. arr1 = nullptr;\r\n\
  459. int[] arr2 = new int[200000];\r\n\
  460. return arr2.size;";
  461. for(int t = 0; t < 2; t++)
  462. {
  463. testsCount[t]++;
  464. if(Tests::RunCode(testGCGlobalLimit, t, "200000", "GC collection before global limit exceeded error"))
  465. testsPassed[t]++;
  466. }
  467. }
  468. };
  469. TestGCGlobalLimit testGCGlobalLimit;
  470. struct TestRestore : TestQueue
  471. {
  472. virtual void Run()
  473. {
  474. nullcTerminate();
  475. nullcInit(MODULE_PATH);
  476. nullcInitTypeinfoModule();
  477. nullcInitFileModule();
  478. nullcInitMathModule();
  479. nullcInitVectorModule();
  480. nullcInitRandomModule();
  481. nullcInitDynamicModule();
  482. nullcInitGCModule();
  483. nullcInitIOModule();
  484. nullcInitCanvasModule();
  485. #if defined(_MSC_VER)
  486. nullcInitWindowModule();
  487. #endif
  488. }
  489. };
  490. TestRestore testRestore;