From 92517c145ef84632232baac77aaf613f8f8ec98e Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 1 Jan 2021 18:44:00 +0100 Subject: [PATCH 1/4] assert: refactor to avoid unsafe array iteration --- lib/assert.js | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index 8ca9b211394ba8..4bb63c7fac0419 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -22,10 +22,13 @@ const { ArrayPrototypeIndexOf, + ArrayPrototypeForEach, ArrayPrototypeJoin, ArrayPrototypePush, ArrayPrototypeShift, ArrayPrototypeSlice, + ArrayPrototypeSome, + ArrayPrototypeUnshift, Error, ErrorCaptureStackTrace, FunctionPrototypeBind, @@ -403,7 +406,8 @@ function innerOk(fn, argLen, value, message) { // Pure assertion tests whether a value is truthy, as determined // by !!value. function ok(...args) { - innerOk(ok, args.length, ...args); + ArrayPrototypeUnshift(args, ok, args.length); + ReflectApply(innerOk, null, args); } assert.ok = ok; @@ -543,7 +547,7 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) { class Comparison { constructor(obj, keys, actual) { - for (const key of keys) { + ArrayPrototypeForEach(keys, (key) => { if (key in obj) { if (actual !== undefined && typeof actual[key] === 'string' && @@ -554,7 +558,7 @@ class Comparison { this[key] = obj[key]; } } - } + }); } } @@ -626,14 +630,13 @@ function expectedException(actual, expected, message, fn) { expected, 'may not be an empty object'); } if (isDeepEqual === undefined) lazyLoadComparison(); - for (const key of keys) { - if (typeof actual[key] === 'string' && - isRegExp(expected[key]) && - RegExpPrototypeTest(expected[key], actual[key])) { - continue; + ArrayPrototypeForEach(keys, (key) => { + if (typeof actual[key] !== 'string' || + !isRegExp(expected[key]) || + !RegExpPrototypeTest(expected[key], actual[key])) { + compareExceptionKey(actual, expected, key, message, keys, fn); } - compareExceptionKey(actual, expected, key, message, keys, fn); - } + }); return; } // Guard instanceof against arrow functions as they don't have a prototype. @@ -837,19 +840,23 @@ function expectsNoError(stackStartFn, actual, error, message) { } assert.throws = function throws(promiseFn, ...args) { - expectsError(throws, getActual(promiseFn), ...args); + ArrayPrototypeUnshift(args, throws, getActual(promiseFn)); + ReflectApply(expectsError, null, args); }; assert.rejects = async function rejects(promiseFn, ...args) { - expectsError(rejects, await waitForActual(promiseFn), ...args); + ArrayPrototypeUnshift(args, rejects, await waitForActual(promiseFn)); + ReflectApply(expectsError, null, args); }; assert.doesNotThrow = function doesNotThrow(fn, ...args) { - expectsNoError(doesNotThrow, getActual(fn), ...args); + ArrayPrototypeUnshift(args, doesNotThrow, getActual(fn)); + ReflectApply(expectsNoError, null, args); }; assert.doesNotReject = async function doesNotReject(fn, ...args) { - expectsNoError(doesNotReject, await waitForActual(fn), ...args); + ArrayPrototypeUnshift(args, doesNotReject, await waitForActual(fn)); + ReflectApply(expectsNoError, null, args); }; assert.ifError = function ifError(err) { @@ -884,15 +891,15 @@ assert.ifError = function ifError(err) { ArrayPrototypeShift(tmp2); // Filter all frames existing in err.stack. let tmp1 = StringPrototypeSplit(newErr.stack, '\n'); - for (const errFrame of tmp2) { + ArrayPrototypeSome(tmp2, (errFrame) => { // Find the first occurrence of the frame. const pos = ArrayPrototypeIndexOf(tmp1, errFrame); if (pos !== -1) { // Only keep new frames. tmp1 = ArrayPrototypeSlice(tmp1, 0, pos); - break; + return true; } - } + }); newErr.stack = `${ArrayPrototypeJoin(tmp1, '\n')}\n${ArrayPrototypeJoin(tmp2, '\n')}`; } @@ -948,7 +955,8 @@ assert.CallTracker = CallTracker; // Expose a strict only variant of assert function strict(...args) { - innerOk(strict, args.length, ...args); + ArrayPrototypeUnshift(args, strict, args.length); + ReflectApply(innerOk, null, args); } assert.strict = ObjectAssign(strict, assert, { equal: assert.strictEqual, From 3c046c5f6a21effd060df843db3bc3e702dc7aff Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 3 Jan 2021 16:53:28 +0100 Subject: [PATCH 2/4] fixup! assert: refactor to avoid unsafe array iteration --- lib/assert.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index 4bb63c7fac0419..b276c7085516ea 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -377,7 +377,7 @@ function getErrMessage(message, fn) { } } -function innerOk(fn, argLen, value, message) { +function innerOk(fn, { length: argLen, 0: value, 1: message }) { if (!value) { let generatedMessage = false; @@ -406,8 +406,7 @@ function innerOk(fn, argLen, value, message) { // Pure assertion tests whether a value is truthy, as determined // by !!value. function ok(...args) { - ArrayPrototypeUnshift(args, ok, args.length); - ReflectApply(innerOk, null, args); + innerOk(ok, args); } assert.ok = ok; @@ -850,13 +849,11 @@ assert.rejects = async function rejects(promiseFn, ...args) { }; assert.doesNotThrow = function doesNotThrow(fn, ...args) { - ArrayPrototypeUnshift(args, doesNotThrow, getActual(fn)); - ReflectApply(expectsNoError, null, args); + expectsNoError(doesNotThrow, getActual(fn), ...args); }; assert.doesNotReject = async function doesNotReject(fn, ...args) { - ArrayPrototypeUnshift(args, doesNotReject, await waitForActual(fn)); - ReflectApply(expectsNoError, null, args); + expectsNoError(doesNotReject, await waitForActual(fn), ...args); }; assert.ifError = function ifError(err) { @@ -955,8 +952,7 @@ assert.CallTracker = CallTracker; // Expose a strict only variant of assert function strict(...args) { - ArrayPrototypeUnshift(args, strict, args.length); - ReflectApply(innerOk, null, args); + innerOk(strict, args); } assert.strict = ObjectAssign(strict, assert, { equal: assert.strictEqual, From 3d002ffcb1c11736073ce8351fb61d2c8ad04ced Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 3 Jan 2021 19:37:24 +0100 Subject: [PATCH 3/4] fixup! assert: refactor to avoid unsafe array iteration --- lib/assert.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index b276c7085516ea..f4ab7a4ff63266 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -28,7 +28,6 @@ const { ArrayPrototypeShift, ArrayPrototypeSlice, ArrayPrototypeSome, - ArrayPrototypeUnshift, Error, ErrorCaptureStackTrace, FunctionPrototypeBind, @@ -741,7 +740,7 @@ async function waitForActual(promiseFn) { return NO_EXCEPTION_SENTINEL; } -function expectsError(stackStartFn, actual, error, message) { +function expectsError(stackStartFn, actual, { 0: error, 1: message }) { if (typeof error === 'string') { if (arguments.length === 4) { throw new ERR_INVALID_ARG_TYPE('error', @@ -813,7 +812,7 @@ function hasMatchingError(actual, expected) { return ReflectApply(expected, {}, [actual]) === true; } -function expectsNoError(stackStartFn, actual, error, message) { +function expectsNoError(stackStartFn, actual, { 0: error, 1: message }) { if (actual === NO_EXCEPTION_SENTINEL) return; @@ -839,21 +838,19 @@ function expectsNoError(stackStartFn, actual, error, message) { } assert.throws = function throws(promiseFn, ...args) { - ArrayPrototypeUnshift(args, throws, getActual(promiseFn)); - ReflectApply(expectsError, null, args); + expectsError(throws, getActual(promiseFn), args); }; assert.rejects = async function rejects(promiseFn, ...args) { - ArrayPrototypeUnshift(args, rejects, await waitForActual(promiseFn)); - ReflectApply(expectsError, null, args); + expectsError(rejects, await waitForActual(promiseFn), args); }; assert.doesNotThrow = function doesNotThrow(fn, ...args) { - expectsNoError(doesNotThrow, getActual(fn), ...args); + expectsNoError(doesNotThrow, getActual(fn), args); }; assert.doesNotReject = async function doesNotReject(fn, ...args) { - expectsNoError(doesNotReject, await waitForActual(fn), ...args); + expectsNoError(doesNotReject, await waitForActual(fn), args); }; assert.ifError = function ifError(err) { From 7c91e3cbae6545e13ae8415b1130e936957a1d6a Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 3 Jan 2021 22:35:22 +0100 Subject: [PATCH 4/4] fixup! assert: refactor to avoid unsafe array iteration --- lib/assert.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index f4ab7a4ff63266..e59ac3fdc3ce83 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -740,9 +740,9 @@ async function waitForActual(promiseFn) { return NO_EXCEPTION_SENTINEL; } -function expectsError(stackStartFn, actual, { 0: error, 1: message }) { +function expectsError(stackStartFn, actual, { 0: error, 1: message, length }) { if (typeof error === 'string') { - if (arguments.length === 4) { + if (length === 2) { throw new ERR_INVALID_ARG_TYPE('error', ['Object', 'Error', 'Function', 'RegExp'], error);