Skip to content

Commit 45532fc

Browse files
committed
test: cover huge Error.stackTraceLimit values
With --trace-uncaught, large Error.stackTraceLimit values overflowed when V8 converted the limit into raw CallSiteInfo slots, either aborting with `Check failed: new_capacity > 0.` or silently dropping frames from error.stack. The V8 cctest for the fix does not run in the regular Node.js CI, so cover the behavior from JavaScript as well. Refs: #66074 Assisted-by: a closed-source coding agent Signed-off-by: Eliau Elkouby <145869377+eliau2005@users.noreply.github.com>
1 parent 5f69d81 commit 45532fc

1 file changed

Lines changed: 59 additions & 0 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Flags: --trace-uncaught
2+
'use strict';
3+
4+
// Regression test for https://github.com/nodejs/node/issues/66074.
5+
// When the isolate captures stack traces for uncaught exceptions (as it does
6+
// with --trace-uncaught or an attached inspector), a large
7+
// Error.stackTraceLimit used to overflow when converted into a number of raw
8+
// CallSiteInfo slots. Depending on the value, this either aborted the process
9+
// with `Check failed: new_capacity > 0.` or silently dropped frames from
10+
// error.stack.
11+
12+
require('../common');
13+
const assert = require('assert');
14+
const { spawnSyncAndExit } = require('../common/child_process');
15+
16+
function recurse(n) {
17+
if (n === 0) return new Error('boom');
18+
return recurse(n - 1);
19+
}
20+
21+
function countFrames(limit) {
22+
Error.stackTraceLimit = limit;
23+
const { stack } = recurse(50);
24+
return stack.split('\n').filter((line) => line.startsWith(' at ')).length;
25+
}
26+
27+
const expected = countFrames(1000);
28+
assert.ok(expected > 50, `expected more than 50 frames, got ${expected}`);
29+
30+
for (const limit of [
31+
// Limit * 6 no longer fits in an int32 (6 raw slots per frame).
32+
357913942,
33+
// Limit * 5 no longer fits in an int32 (5 raw slots per frame).
34+
429496730,
35+
// Limit * 6 wraps around to a small positive value.
36+
715827883,
37+
715827884,
38+
// Limit * 5 wraps around to a small positive value.
39+
858993460,
40+
1073741824,
41+
1431655766,
42+
2 ** 31 - 1,
43+
2 ** 32,
44+
Number.MAX_SAFE_INTEGER,
45+
Infinity,
46+
]) {
47+
assert.strictEqual(countFrames(limit), expected, `Error.stackTraceLimit = ${limit}`);
48+
}
49+
50+
// The original reproduction: an uncaught error thrown with an unbounded limit.
51+
spawnSyncAndExit(process.execPath, [
52+
'--trace-uncaught',
53+
'--eval',
54+
'Error.stackTraceLimit = Infinity; throw new Error("boom");',
55+
], {
56+
status: 1,
57+
signal: null,
58+
stderr: /^Thrown at:$/m,
59+
});

0 commit comments

Comments
 (0)