Skip to content

Commit 1fa4037

Browse files
BridgeARTrott
authored andcommitted
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: #29647 Fixes: #29646 Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Minwoo Jung <[email protected]>
1 parent 0c32ca9 commit 1fa4037

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

lib/internal/util/inspect.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ function getEmptyFormatArray() {
351351
return [];
352352
}
353353

354-
function getConstructorName(obj, ctx) {
354+
function getConstructorName(obj, ctx, recurseTimes) {
355355
let firstProto;
356356
const tmp = obj;
357357
while (obj) {
@@ -372,10 +372,23 @@ function getConstructorName(obj, ctx) {
372372
return null;
373373
}
374374

375-
return `${internalGetConstructorName(tmp)} <${inspect(firstProto, {
376-
...ctx,
377-
customInspect: false
378-
})}>`;
375+
const res = internalGetConstructorName(tmp);
376+
377+
if (recurseTimes > ctx.depth && ctx.depth !== null) {
378+
return `${res} <Complex prototype>`;
379+
}
380+
381+
const protoConstr = getConstructorName(firstProto, ctx, recurseTimes + 1);
382+
383+
if (protoConstr === null) {
384+
return `${res} <${inspect(firstProto, {
385+
...ctx,
386+
customInspect: false,
387+
depth: -1
388+
})}>`;
389+
}
390+
391+
return `${res} <${protoConstr}>`;
379392
}
380393

381394
function getPrefix(constructor, tag, fallback) {
@@ -581,7 +594,7 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
581594
function formatRaw(ctx, value, recurseTimes, typedArray) {
582595
let keys;
583596

584-
const constructor = getConstructorName(value, ctx);
597+
const constructor = getConstructorName(value, ctx, recurseTimes);
585598
let tag = value[Symbol.toStringTag];
586599
// Only list the tag in case it's non-enumerable / not an own property.
587600
// Otherwise we'd print this twice.

test/parallel/test-util-inspect.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2114,6 +2114,21 @@ assert.strictEqual(
21142114
inspect(obj),
21152115
"Array <[Object: null prototype] {}> { '0': 1, '1': 2, '2': 3 }"
21162116
);
2117+
2118+
StorageObject.prototype = Object.create(null);
2119+
Object.setPrototypeOf(StorageObject.prototype, Object.create(null));
2120+
Object.setPrototypeOf(
2121+
Object.getPrototypeOf(StorageObject.prototype),
2122+
Object.create(null)
2123+
);
2124+
assert.strictEqual(
2125+
util.inspect(new StorageObject()),
2126+
'StorageObject <Object <Object <[Object: null prototype] {}>>> {}'
2127+
);
2128+
assert.strictEqual(
2129+
util.inspect(new StorageObject(), { depth: 1 }),
2130+
'StorageObject <Object <Object <Complex prototype>>> {}'
2131+
);
21172132
}
21182133

21192134
// Check that the fallback always works.

0 commit comments

Comments
 (0)