summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Bridgewater <ruben@bridgewater.de>2019-09-21 21:26:02 +0200
committerRuben Bridgewater <ruben@bridgewater.de>2019-09-25 18:21:07 +0200
commit68630c5b65326fe27cbf107d0e91d58a46658b2d (patch)
tree74a048863563f716d27d4d22b616a28ffdac1382
parent6272f82c07e913a76a316a786c9aadbc09f953ff (diff)
downloadnode-new-68630c5b65326fe27cbf107d0e91d58a46658b2d.tar.gz
console,util: fix missing recursion end while inspecting prototypes
This makes sure prototypes won't be inspected infinitely for some obscure object creations. The depth is now taken into account and the recursion ends when the depth limit is reached. PR-URL: https://github.com/nodejs/node/pull/29647 Fixes: https://github.com/nodejs/node/issues/29646 Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Minwoo Jung <minwoo@nodesource.com>
-rw-r--r--lib/internal/util/inspect.js25
-rw-r--r--test/parallel/test-util-inspect.js15
2 files changed, 34 insertions, 6 deletions
diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js
index 2b321002c2..7ad94600b7 100644
--- a/lib/internal/util/inspect.js
+++ b/lib/internal/util/inspect.js
@@ -351,7 +351,7 @@ function getEmptyFormatArray() {
return [];
}
-function getConstructorName(obj, ctx) {
+function getConstructorName(obj, ctx, recurseTimes) {
let firstProto;
const tmp = obj;
while (obj) {
@@ -372,10 +372,23 @@ function getConstructorName(obj, ctx) {
return null;
}
- return `${internalGetConstructorName(tmp)} <${inspect(firstProto, {
- ...ctx,
- customInspect: false
- })}>`;
+ const res = internalGetConstructorName(tmp);
+
+ if (recurseTimes > ctx.depth && ctx.depth !== null) {
+ return `${res} <Complex prototype>`;
+ }
+
+ const protoConstr = getConstructorName(firstProto, ctx, recurseTimes + 1);
+
+ if (protoConstr === null) {
+ return `${res} <${inspect(firstProto, {
+ ...ctx,
+ customInspect: false,
+ depth: -1
+ })}>`;
+ }
+
+ return `${res} <${protoConstr}>`;
}
function getPrefix(constructor, tag, fallback) {
@@ -570,7 +583,7 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
function formatRaw(ctx, value, recurseTimes, typedArray) {
let keys;
- const constructor = getConstructorName(value, ctx);
+ const constructor = getConstructorName(value, ctx, recurseTimes);
let tag = value[Symbol.toStringTag];
// Only list the tag in case it's non-enumerable / not an own property.
// Otherwise we'd print this twice.
diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js
index 4cb8224c54..27179cf51c 100644
--- a/test/parallel/test-util-inspect.js
+++ b/test/parallel/test-util-inspect.js
@@ -2092,6 +2092,21 @@ assert.strictEqual(
inspect(obj),
"Array <[Object: null prototype] {}> { '0': 1, '1': 2, '2': 3 }"
);
+
+ StorageObject.prototype = Object.create(null);
+ Object.setPrototypeOf(StorageObject.prototype, Object.create(null));
+ Object.setPrototypeOf(
+ Object.getPrototypeOf(StorageObject.prototype),
+ Object.create(null)
+ );
+ assert.strictEqual(
+ util.inspect(new StorageObject()),
+ 'StorageObject <Object <Object <[Object: null prototype] {}>>> {}'
+ );
+ assert.strictEqual(
+ util.inspect(new StorageObject(), { depth: 1 }),
+ 'StorageObject <Object <Object <Complex prototype>>> {}'
+ );
}
// Check that the fallback always works.