Skip to content

Commit bc52bd5

Browse files
committed
util: fix infinite recursion during inspection
A specially crafted object with circular structures behind getters could cause a infinite recursion. This is now fixed by detecting the objects as already visited. Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de>
1 parent bb13469 commit bc52bd5

File tree

2 files changed

+54
-15
lines changed

2 files changed

+54
-15
lines changed

lib/internal/util/inspect.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ function addPrototypeProperties(ctx, main, obj, recurseTimes, output) {
617617
}
618618
// Get all own property names and symbols.
619619
keys = ReflectOwnKeys(obj);
620+
ctx.seen.push(main);
620621
for (const key of keys) {
621622
// Ignore the `constructor` property and keys that exist on layers above.
622623
if (key === 'constructor' ||
@@ -637,6 +638,7 @@ function addPrototypeProperties(ctx, main, obj, recurseTimes, output) {
637638
ArrayPrototypePush(output, value);
638639
}
639640
}
641+
ctx.seen.pop();
640642
// Limit the inspection to up to three prototype layers. Using `recurseTimes`
641643
// is not a good choice here, because it's as if the properties are declared
642644
// on the current object from the users perspective.

test/parallel/test-util-inspect-getters-accessing-this.js

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,61 @@ require('../common');
77

88
const assert = require('assert');
99

10-
const util = require('util');
10+
const { inspect } = require('util');
1111

12-
class X {
13-
constructor() {
14-
this._y = 123;
15-
}
12+
{
13+
class X {
14+
constructor() {
15+
this._y = 123;
16+
}
1617

17-
get y() {
18-
return this._y;
18+
get y() {
19+
return this._y;
20+
}
1921
}
22+
23+
const result = inspect(new X(), {
24+
getters: true,
25+
showHidden: true
26+
});
27+
28+
assert.strictEqual(
29+
result,
30+
'X { _y: 123, [y]: [Getter: 123] }'
31+
);
2032
}
2133

22-
const result = util.inspect(new X(), {
23-
getters: true,
24-
showHidden: true
25-
});
34+
// Regression test for https://github.com/nodejs/node/issues/37054
35+
{
36+
class A {
37+
constructor(B) {
38+
this.B = B;
39+
}
40+
get b() {
41+
return this.B;
42+
}
43+
}
44+
45+
class B {
46+
constructor() {
47+
this.A = new A(this);
48+
}
49+
get a() {
50+
return this.A;
51+
}
52+
}
53+
54+
const result = inspect(new B(), {
55+
depth: 1,
56+
getters: true,
57+
showHidden: true
58+
});
2659

27-
assert.strictEqual(
28-
result,
29-
'X { _y: 123, [y]: [Getter: 123] }'
30-
);
60+
assert.strictEqual(
61+
result,
62+
'<ref *1> B {\n' +
63+
' A: A { B: [Circular *1], [b]: [Getter] [Circular *1] },\n' +
64+
' [a]: [Getter] A { B: [Circular *1], [b]: [Getter] [Circular *1] }\n' +
65+
'}',
66+
);
67+
}

0 commit comments

Comments
 (0)