From 1fa403762c035dca35bae9a18a4e4c3edf9d55f3 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 21 Sep 2019 21:26:02 +0200 Subject: 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 Reviewed-By: Minwoo Jung --- lib/internal/util/inspect.js | 25 +++++++++++++++++++------ test/parallel/test-util-inspect.js | 15 +++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index de044447b3..6401e30e92 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} `; + } + + 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) { @@ -581,7 +594,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 64682d9c17..fc0bb345da 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -2114,6 +2114,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 >> {}' + ); + assert.strictEqual( + util.inspect(new StorageObject(), { depth: 1 }), + 'StorageObject >> {}' + ); } // Check that the fallback always works. -- cgit v1.2.3