Skip to content

Commit 68630c5

Browse files
committed
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 6272f82 commit 68630c5

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

lib/internal/util/inspect.js

+19-6
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) {
@@ -570,7 +583,7 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
570583
function formatRaw(ctx, value, recurseTimes, typedArray) {
571584
let keys;
572585

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

test/parallel/test-util-inspect.js

+15
Original file line numberDiff line numberDiff line change
@@ -2092,6 +2092,21 @@ assert.strictEqual(
20922092
inspect(obj),
20932093
"Array <[Object: null prototype] {}> { '0': 1, '1': 2, '2': 3 }"
20942094
);
2095+
2096+
StorageObject.prototype = Object.create(null);
2097+
Object.setPrototypeOf(StorageObject.prototype, Object.create(null));
2098+
Object.setPrototypeOf(
2099+
Object.getPrototypeOf(StorageObject.prototype),
2100+
Object.create(null)
2101+
);
2102+
assert.strictEqual(
2103+
util.inspect(new StorageObject()),
2104+
'StorageObject <Object <Object <[Object: null prototype] {}>>> {}'
2105+
);
2106+
assert.strictEqual(
2107+
util.inspect(new StorageObject(), { depth: 1 }),
2108+
'StorageObject <Object <Object <Complex prototype>>> {}'
2109+
);
20952110
}
20962111

20972112
// Check that the fallback always works.

0 commit comments

Comments
 (0)