misc_bugs.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Copyright (c) ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. // @ts-check
  7. /// <reference path="..\UnitTestFramework\UnitTestFramework.js" />
  8. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  9. var tests = [
  10. {
  11. name: "calling Symbol.toPrimitive on Date prototype should not AV",
  12. body: function () {
  13. Date.prototype[Symbol.toPrimitive].call({}, 'strin' + 'g');
  14. }
  15. },
  16. {
  17. name: "updated stackTraceLimit should not fire re-entrancy assert",
  18. body: function () {
  19. Error.__defineGetter__('stackTraceLimit', function () { return 1; });
  20. assert.throws(() => Array.prototype.map.call([]));
  21. }
  22. },
  23. {
  24. name: "Array.prototype.slice should not fire re-entrancy error when the species returns proxy",
  25. body: function () {
  26. let arr = [1, 2];
  27. arr.__proto__ = {
  28. constructor: {
  29. [Symbol.species]: function () {
  30. return new Proxy({}, {
  31. defineProperty(...args) {
  32. return Reflect.defineProperty(...args);
  33. }
  34. });
  35. }
  36. }
  37. }
  38. Array.prototype.slice.call(arr);
  39. }
  40. },
  41. {
  42. name: "rest param under eval with arguments usage in the body should not fail assert",
  43. body: function () {
  44. f();
  45. function f() {
  46. eval("function bar(...x){arguments;}")
  47. }
  48. }
  49. },
  50. {
  51. name: "Token left after parsing lambda result to the syntax error",
  52. body: function () {
  53. assert.throws(() => { eval('function foo ([ [] = () => { } = {a2:z2}]) { };'); });
  54. }
  55. },
  56. {
  57. name: "Token left after parsing lambda in ternary operator should not throw",
  58. body: function () {
  59. assert.doesNotThrow(() => { eval('function foo () { true ? e => {} : 1};'); });
  60. }
  61. },
  62. {
  63. name: "ArrayBuffer.slice with proxy constructor should not fail fast",
  64. body: function () {
  65. let arr = new ArrayBuffer(10);
  66. arr.constructor = new Proxy(ArrayBuffer, {});
  67. arr.slice(1, 2);
  68. }
  69. },
  70. {
  71. name: "Large proxy chain should not cause IsConstructor to crash on stack overflow",
  72. body: function () {
  73. let p = new Proxy(Object, {});
  74. for (let i = 0; i < 20000; ++i) {
  75. p = new Proxy(p, {});
  76. }
  77. try {
  78. let a = new p();
  79. }
  80. catch (e) {
  81. }
  82. }
  83. },
  84. {
  85. name: "splice an array which has getter/setter at 4294967295 should not fail due to re-entrancy error",
  86. body: function () {
  87. var base = 4294967290;
  88. var arr = [];
  89. for (var i = 0; i < 10; i++) {
  90. arr[base + i] = 100 + i;
  91. }
  92. Object.defineProperty(arr, 4294967295, {
  93. get: function () { }, set: function (b) { }
  94. }
  95. );
  96. assert.throws(() => { arr.splice(4294967290, 0, 200, 201, 202, 203, 204, 205, 206); });
  97. }
  98. },
  99. {
  100. name: "Passing args count near 2**16 should not fire assert (OS# 17406027)",
  101. body: function () {
  102. try {
  103. eval.call(...(new Array(2 ** 16)));
  104. } catch (e) { }
  105. try {
  106. eval.call(...(new Array(2 ** 16 + 1)));
  107. } catch (e) { }
  108. try {
  109. var sc1 = WScript.LoadScript(`function foo() {}`, "samethread");
  110. sc1.foo(...(new Array(2 ** 16)));
  111. } catch (e) { }
  112. try {
  113. var sc2 = WScript.LoadScript(`function foo() {}`, "samethread");
  114. sc2.foo(...(new Array(2 ** 16 + 1)));
  115. } catch (e) { }
  116. try {
  117. function foo() { }
  118. Reflect.construct(foo, new Array(2 ** 16 - 3));
  119. } catch (e) { }
  120. try {
  121. function foo() { }
  122. Reflect.construct(foo, new Array(2 ** 16 - 2));
  123. } catch (e) { }
  124. try {
  125. function foo() { }
  126. var bar = foo.bind({}, 1);
  127. new bar(...(new Array(2 ** 16 + 1)))
  128. } catch (e) { }
  129. }
  130. },
  131. {
  132. name: "Using RegExp as newTarget should not assert",
  133. body: function () {
  134. var v0 = function () { this.a; };
  135. var v1 = class extends v0 { constructor() { super(); } };
  136. Reflect.construct(v1, [], RegExp);
  137. }
  138. },
  139. {
  140. name: "getPrototypeOf Should not be called when set as prototype",
  141. body: function () {
  142. var p = new Proxy({}, {
  143. getPrototypeOf: function () {
  144. assert.fail("this should not be called")
  145. return {};
  146. }
  147. });
  148. var obj = {};
  149. obj.__proto__ = p; // This should not call the getPrototypeOf
  150. var obj1 = {};
  151. Object.setPrototypeOf(obj1, p); // This should not call the getPrototypeOf
  152. var obj2 = { __proto__: p }; // This should not call the getPrototypeOf
  153. }
  154. },
  155. {
  156. name: "Cross-site activation object",
  157. body: function () {
  158. var tests = [0, 0];
  159. tests.forEach(function () {
  160. var eval = WScript.LoadScript(0, "samethread").eval;
  161. eval(0);
  162. });
  163. }
  164. },
  165. {
  166. name: "Destructuring declaration should return undefined",
  167. body: function () {
  168. assert.areEqual(undefined, eval("var {x} = {};"));
  169. assert.areEqual(undefined, eval("let {x,y} = {};"));
  170. assert.areEqual(undefined, eval("const [z] = [];"));
  171. assert.areEqual(undefined, eval("let {x} = {}, y = 1, {z} = {};"));
  172. assert.areEqual([1], eval("let {x} = {}; [x] = [1]"));
  173. }
  174. },
  175. {
  176. name: "Strict Mode : throw type error when the handler returns falsy value",
  177. body: function () {
  178. assert.throws(() => { "use strict"; let p1 = new Proxy({}, { set() { } }); p1.foo = 1; }, TypeError, "returning undefined on set handler is return false which will throw type error", "Proxy 'set' handler returned falsish for property 'foo'");
  179. assert.throws(() => { "use strict"; let p1 = new Proxy({}, { deleteProperty() { } }); delete p1.foo; }, TypeError, "returning undefined on deleteProperty handler is return false which will throw type error", "Proxy 'deleteProperty' handler returned falsish for property 'foo'");
  180. assert.throws(() => { "use strict"; let p1 = new Proxy({}, { set() { return false; } }); p1.foo = 1; }, TypeError, "set handler is returning false which will throw type error", "Proxy 'set' handler returned falsish for property 'foo'");
  181. assert.throws(() => { "use strict"; let p1 = new Proxy({}, { deleteProperty() { return false; } }); delete p1.foo; }, TypeError, "deleteProperty handler is returning false which will throw type error", "Proxy 'deleteProperty' handler returned falsish for property 'foo'");
  182. const proxy = new Proxy({}, {
  183. defineProperty() {
  184. return false;
  185. }
  186. });
  187. assert.doesNotThrow(() => {
  188. proxy.a = {};
  189. }, "Set property in NON-strict mode does NOT throw if trap returns falsy");
  190. assert.throws(() => {
  191. "use strict";
  192. proxy.b = {};
  193. }, TypeError, "Set property in strict mode does DOES throw if trap returns falsy");
  194. assert.throws(() => {
  195. Object.defineProperty(proxy, "c", {
  196. value: {}
  197. });
  198. }, TypeError, "Calling 'Object.defineProperty' throws if trap returns falsy");
  199. }
  200. },
  201. {
  202. name: "Generator : testing recursion",
  203. body: function () {
  204. // This will throw out of stack error
  205. assert.throws(() => {
  206. function foo() {
  207. function* f() {
  208. yield foo();
  209. }
  210. f().next();
  211. }
  212. foo();
  213. });
  214. }
  215. },
  216. {
  217. name: "destructuring : testing recursion",
  218. body: function () {
  219. try {
  220. eval(`
  221. var ${'['.repeat(6631)}
  222. `);
  223. assert.fail();
  224. }
  225. catch (e) {
  226. }
  227. try {
  228. eval(`
  229. var {${'a:{'.repeat(6631)}
  230. `);
  231. assert.fail();
  232. }
  233. catch (e) {
  234. }
  235. }
  236. },
  237. {
  238. name: "CrossSite issue while array concat OS: 18874745",
  239. body: function () {
  240. function test0() {
  241. var IntArr0 = Array();
  242. var sc0Code = `
  243. Object.defineProperty(Array, Symbol.species, { value : function() {
  244. return IntArr0;
  245. }
  246. }
  247. );
  248. test = function(a, list) {
  249. return [a].concat(list);
  250. }
  251. function out() {
  252. test({}, [1]);
  253. }
  254. `;
  255. var sc0 = WScript.LoadScript(sc0Code, 'samethread');
  256. sc0.IntArr0 = IntArr0;
  257. sc0.out();
  258. }
  259. test0();
  260. }
  261. },
  262. {
  263. name: "Init box javascript array : OS : 20517662",
  264. body: function () {
  265. var obj = {};
  266. obj[0] = 11;
  267. obj[1] = {};
  268. obj[17] = 222;
  269. obj[35] = 333; // This is will increase the size past the inline segment
  270. Object.assign({}, obj); // The InitBoxedInlineSegments will be called due to this call.
  271. }
  272. },
  273. {
  274. name: "calling promise's function as constructor should not be allowed",
  275. body: function () {
  276. var var_0 = new Promise(function () { });
  277. var var_1 = function () { };
  278. var_0.then = function (a, b) {
  279. var_2 = b;
  280. };
  281. var_3 = Promise.prototype.finally.call(var_0, var_1);
  282. assert.throws(() => { new var_2([]).var_3(); }, TypeError);
  283. }
  284. },
  285. {
  286. name: "issue : 6174 : calling ToNumber for the fill value for typedarray.prototype.fill",
  287. body: function () {
  288. let arr1 = new Uint32Array(5);
  289. let valueOfCalled = false;
  290. let p1 = new Proxy([], {
  291. get: function (oTarget, sKey) {
  292. if (sKey.toString() == 'valueOf') {
  293. valueOfCalled = true;
  294. }
  295. return Reflect.get(oTarget, sKey);
  296. }
  297. });
  298. Uint32Array.prototype.fill.call(arr1, p1, 5, 1);
  299. assert.isTrue(valueOfCalled);
  300. }
  301. },
  302. {
  303. name: "class name should not change if calling multiple times",
  304. body: function () {
  305. function getClass() {
  306. class A {
  307. constructor() {
  308. }
  309. };
  310. return A;
  311. }
  312. let f1 = getClass();
  313. let f2 = getClass();
  314. let f3 = getClass();
  315. assert.areEqual("A", f1.name);
  316. assert.areEqual("A", f2.name);
  317. assert.areEqual("A", f3.name);
  318. }
  319. },
  320. {
  321. name: "should throw syntax error when expression within if is comma-terminated",
  322. body: function () {
  323. assert.throws(() => { eval('var f = function () { var f = 0; if (f === 0,) print("run_here"); }; f();'); }, SyntaxError);
  324. }
  325. },
  326. {
  327. name: "Correct parsing of (missing) expression bodies",
  328. body() {
  329. assert.throws(() => eval("if(true)"), SyntaxError);
  330. assert.doesNotThrow(() => eval("if(true);"));
  331. assert.doesNotThrow(() => eval("if(true){}"));
  332. assert.throws(() => eval("if(true){}else"), SyntaxError);
  333. assert.doesNotThrow(() => eval("if(true){}else;"));
  334. assert.doesNotThrow(() => eval("if(true){}else{}"));
  335. assert.throws(() => eval("while(false)"), SyntaxError);
  336. assert.doesNotThrow(() => eval("while(false);"));
  337. assert.doesNotThrow(() => eval("while(false){}"));
  338. assert.throws(() => eval("for(;false;)"), SyntaxError);
  339. assert.doesNotThrow(() => eval("for(;false;);"));
  340. assert.doesNotThrow(() => eval("for(;false;){}"));
  341. assert.throws(() => eval("do"), SyntaxError);
  342. }
  343. }
  344. ];
  345. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });