From 32a2a9a53972568f4669ef9121c1fdef9042c0ce Mon Sep 17 00:00:00 2001 From: Raz Luvaton <16746759+rluvaton@users.noreply.github.com> Date: Wed, 5 Jul 2023 20:51:39 +0300 Subject: [PATCH 1/2] assert: add __proto__ null --- lib/assert.js | 33 ++++++++++++++++++++------ lib/internal/assert/assertion_error.js | 3 +++ lib/internal/assert/calltracker.js | 5 +++- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index b7d7a3da01d520..1659896ec0e87b 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -111,7 +111,7 @@ let warned = false; const assert = module.exports = ok; -const NO_EXCEPTION_SENTINEL = {}; +const NO_EXCEPTION_SENTINEL = { __proto__: null }; // All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that @@ -159,6 +159,7 @@ function fail(actual, expected, message, operator, stackStartFn) { if (message instanceof Error) throw message; const errArgs = { + __proto__: null, actual, expected, operator: operator === undefined ? 'fail' : operator, @@ -253,7 +254,7 @@ function parseCode(code, offset) { let node; let start; // Parse the read code until the correct expression is found. - for (const token of tokenizer(code, { ecmaVersion: 'latest' })) { + for (const token of tokenizer(code, { __proto__: null, ecmaVersion: 'latest' })) { start = token.start; if (start > offset) { // No matching expression found. This could happen if the assert @@ -261,7 +262,7 @@ function parseCode(code, offset) { break; } try { - node = parseExpressionAt(code, start, { ecmaVersion: 'latest' }); + node = parseExpressionAt(code, start, { __proto__: null, ecmaVersion: 'latest' }); // Find the CallExpression in the tree. node = findNodeAround(node, offset, 'CallExpression'); if (node?.node.end >= offset) { @@ -289,7 +290,7 @@ function getErrMessage(message, fn) { if (errorStackTraceLimitIsWritable) Error.stackTraceLimit = 1; // We only need the stack trace. To minimize the overhead use an object // instead of an error. - const err = {}; + const err = { __proto__: null }; ErrorCaptureStackTrace(err, fn); if (errorStackTraceLimitIsWritable) Error.stackTraceLimit = tmpLimit; @@ -389,6 +390,7 @@ function innerOk(fn, argLen, value, message) { } const err = new AssertionError({ + __proto__: null, actual: value, expected: true, message, @@ -426,6 +428,7 @@ assert.equal = function equal(actual, expected, message) { // eslint-disable-next-line eqeqeq if (actual != expected && (!NumberIsNaN(actual) || !NumberIsNaN(expected))) { innerFail({ + __proto__: null, actual, expected, message, @@ -450,6 +453,7 @@ assert.notEqual = function notEqual(actual, expected, message) { // eslint-disable-next-line eqeqeq if (actual == expected || (NumberIsNaN(actual) && NumberIsNaN(expected))) { innerFail({ + __proto__: null, actual, expected, message, @@ -473,6 +477,7 @@ assert.deepEqual = function deepEqual(actual, expected, message) { if (isDeepEqual === undefined) lazyLoadComparison(); if (!isDeepEqual(actual, expected)) { innerFail({ + __proto__: null, actual, expected, message, @@ -496,6 +501,7 @@ assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if (isDeepEqual === undefined) lazyLoadComparison(); if (isDeepEqual(actual, expected)) { innerFail({ + __proto__: null, actual, expected, message, @@ -521,6 +527,7 @@ assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { if (isDeepEqual === undefined) lazyLoadComparison(); if (!isDeepStrictEqual(actual, expected)) { innerFail({ + __proto__: null, actual, expected, message, @@ -546,6 +553,7 @@ function notDeepStrictEqual(actual, expected, message) { if (isDeepEqual === undefined) lazyLoadComparison(); if (isDeepStrictEqual(actual, expected)) { innerFail({ + __proto__: null, actual, expected, message, @@ -568,6 +576,7 @@ assert.strictEqual = function strictEqual(actual, expected, message) { } if (!ObjectIs(actual, expected)) { innerFail({ + __proto__: null, actual, expected, message, @@ -590,6 +599,7 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) { } if (ObjectIs(actual, expected)) { innerFail({ + __proto__: null, actual, expected, message, @@ -624,6 +634,7 @@ function compareExceptionKey(actual, expected, key, message, keys, fn) { const b = new Comparison(expected, keys, actual); const err = new AssertionError({ + __proto__: null, actual: a, expected: b, operator: 'deepStrictEqual', @@ -635,6 +646,7 @@ function compareExceptionKey(actual, expected, key, message, keys, fn) { throw err; } innerFail({ + __proto__: null, actual, expected, message, @@ -664,6 +676,7 @@ function expectedException(actual, expected, message, fn) { // Handle primitives properly. } else if (typeof actual !== 'object' || actual === null) { const err = new AssertionError({ + __proto__: null, actual, expected, message, @@ -715,13 +728,13 @@ function expectedException(actual, expected, message, fn) { message += `\n\nError message:\n\n${actual.message}`; } } else { - message += `"${inspect(actual, { depth: -1 })}"`; + message += `"${inspect(actual, { __proto__: null, depth: -1 })}"`; } } throwError = true; } else { // Check validation functions return value. - const res = ReflectApply(expected, {}, [actual]); + const res = ReflectApply(expected, { __proto__: null }, [actual]); if (res !== true) { if (!message) { generatedMessage = true; @@ -739,6 +752,7 @@ function expectedException(actual, expected, message, fn) { if (throwError) { const err = new AssertionError({ + __proto__: null, actual, expected, message, @@ -833,6 +847,7 @@ function expectsError(stackStartFn, actual, error, message) { details += message ? `: ${message}` : '.'; const fnType = stackStartFn === assert.rejects ? 'rejection' : 'exception'; innerFail({ + __proto__: null, actual: undefined, expected: error, operator: stackStartFn.name, @@ -864,7 +879,7 @@ function hasMatchingError(actual, expected) { if (ObjectPrototypeIsPrototypeOf(Error, expected)) { return false; } - return ReflectApply(expected, {}, [actual]) === true; + return ReflectApply(expected, { __proto__: null }, [actual]) === true; } function expectsNoError(stackStartFn, actual, error, message) { @@ -881,6 +896,7 @@ function expectsNoError(stackStartFn, actual, error, message) { const fnType = stackStartFn === assert.doesNotReject ? 'rejection' : 'exception'; innerFail({ + __proto__: null, actual, expected: error, operator: stackStartFn.name, @@ -951,6 +967,7 @@ assert.ifError = function ifError(err) { } const newErr = new AssertionError({ + __proto__: null, actual: err, expected: null, operator: 'ifError', @@ -1016,6 +1033,7 @@ function internalMatch(string, regexp, message, fn) { 'The input was expected to not match the regular expression ') + `${inspect(regexp)}. Input:\n\n${inspect(string)}\n`); const err = new AssertionError({ + __proto__: null, actual: string, expected: regexp, message, @@ -1061,6 +1079,7 @@ function strict(...args) { } assert.strict = ObjectAssign(strict, assert, { + __proto__: null, equal: assert.strictEqual, deepEqual: assert.deepStrictEqual, notEqual: assert.notStrictEqual, diff --git a/lib/internal/assert/assertion_error.js b/lib/internal/assert/assertion_error.js index f12243790b0506..f2db2d54ed77c8 100644 --- a/lib/internal/assert/assertion_error.js +++ b/lib/internal/assert/assertion_error.js @@ -28,6 +28,7 @@ const { isErrorStackTraceLimitWritable } = require('internal/errors'); const kReadableOperator = { + __proto__: null, deepStrictEqual: 'Expected values to be strictly deep-equal:', strictEqual: 'Expected values to be strictly equal:', strictEqualObject: 'Expected "actual" to be reference-equal to "expected":', @@ -61,6 +62,7 @@ function inspectValue(val) { return inspect( val, { + __proto__: null, compact: false, customInspect: false, depth: 1000, @@ -476,6 +478,7 @@ class AssertionError extends Error { // to the actual error message which contains a combined view of these two // input values. const result = inspect(this, { + __proto__: null, ...ctx, customInspect: false, depth: 0, diff --git a/lib/internal/assert/calltracker.js b/lib/internal/assert/calltracker.js index 0e2275305321ef..8e38d7412229d2 100644 --- a/lib/internal/assert/calltracker.js +++ b/lib/internal/assert/calltracker.js @@ -39,7 +39,7 @@ class CallTrackerContext { track(thisArg, args) { const argsClone = ObjectFreeze(ArrayPrototypeSlice(args)); - ArrayPrototypePush(this.#calls, ObjectFreeze({ thisArg, arguments: argsClone })); + ArrayPrototypePush(this.#calls, ObjectFreeze({ __proto__: null, thisArg, arguments: argsClone })); } get delta() { @@ -59,6 +59,7 @@ class CallTrackerContext { `executed ${this.#expected} time(s) but was ` + `executed ${this.#calls.length} time(s).`; return { + __proto__: null, message, actual: this.#calls.length, expected: this.#expected, @@ -107,6 +108,7 @@ class CallTracker { validateUint32(expected, 'expected', true); const context = new CallTrackerContext({ + __proto__: null, expected, // eslint-disable-next-line no-restricted-syntax stackTrace: new Error(), @@ -144,6 +146,7 @@ class CallTracker { errors[0].message : 'Functions were not called the expected number of times'; throw new AssertionError({ + __proto__: null, message, details: errors, }); From 99dedf0d8b0355eb98a8fe6bfab6e1a7afe0852c Mon Sep 17 00:00:00 2001 From: Raz Luvaton <16746759+rluvaton@users.noreply.github.com> Date: Thu, 6 Jul 2023 00:28:36 +0300 Subject: [PATCH 2/2] assert: dont add __proto__: null for call result --- lib/internal/assert/calltracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/assert/calltracker.js b/lib/internal/assert/calltracker.js index 8e38d7412229d2..9c6397b5ef6f68 100644 --- a/lib/internal/assert/calltracker.js +++ b/lib/internal/assert/calltracker.js @@ -39,7 +39,7 @@ class CallTrackerContext { track(thisArg, args) { const argsClone = ObjectFreeze(ArrayPrototypeSlice(args)); - ArrayPrototypePush(this.#calls, ObjectFreeze({ __proto__: null, thisArg, arguments: argsClone })); + ArrayPrototypePush(this.#calls, ObjectFreeze({ thisArg, arguments: argsClone })); } get delta() {