Skip to content

Commit 807b1e5

Browse files
legendecasRafaelGSS
authored andcommitted
report: get stack trace with cross origin contexts
When a new context with a different security token is entered, or when no context is entered, `StackTrace::CurrentStackTrace` need to be explicitly set with flag `kExposeFramesAcrossSecurityOrigins` to avoid crashing. PR-URL: #44398 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent b17cc87 commit 807b1e5

File tree

4 files changed

+57
-12
lines changed

4 files changed

+57
-12
lines changed

src/node_errors.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,11 @@ void OOMErrorHandler(const char* location, bool is_heap_oom) {
513513
}
514514

515515
if (report_on_fatalerror) {
516+
// Trigger report with the isolate. Environment::GetCurrent may return
517+
// nullptr here:
518+
// - If the OOM is reported by a young generation space allocation,
519+
// Isolate::GetCurrentContext returns an empty handle.
520+
// - Otherwise, Isolate::GetCurrentContext returns a non-empty handle.
516521
TriggerNodeReport(isolate, message, "OOMError", "", Local<Object>());
517522
}
518523

src/node_report.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,12 @@ static void PrintJavaScriptStack(JSONWriter* writer,
470470
void* samples[MAX_FRAME_COUNT];
471471
isolate->GetStackSample(state, samples, MAX_FRAME_COUNT, &info);
472472

473+
constexpr StackTrace::StackTraceOptions stack_trace_options =
474+
static_cast<StackTrace::StackTraceOptions>(
475+
StackTrace::kDetailed |
476+
StackTrace::kExposeFramesAcrossSecurityOrigins);
473477
Local<StackTrace> stack = StackTrace::CurrentStackTrace(
474-
isolate, MAX_FRAME_COUNT, StackTrace::kDetailed);
478+
isolate, MAX_FRAME_COUNT, stack_trace_options);
475479

476480
if (stack->GetFrameCount() == 0) {
477481
PrintEmptyJavaScriptStack(writer);

test/addons/report-api/binding.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <node.h>
22
#include <v8.h>
33

4+
using v8::Context;
45
using v8::FunctionCallbackInfo;
56
using v8::Isolate;
67
using v8::Local;
@@ -43,11 +44,37 @@ void TriggerReportNoEnv(const FunctionCallbackInfo<Value>& args) {
4344
Local<Value>());
4445
}
4546

47+
void TriggerReportNoContext(const FunctionCallbackInfo<Value>& args) {
48+
Isolate* isolate = args.GetIsolate();
49+
Local<Context> context = isolate->GetCurrentContext();
50+
context->Exit();
51+
52+
if (isolate->GetCurrentContext().IsEmpty()) {
53+
node::TriggerNodeReport(
54+
isolate, "FooMessage", "BarTrigger", std::string(), Local<Value>());
55+
}
56+
57+
// Restore current context to avoid crashing in Context::Scope in
58+
// SpinEventLoop.
59+
context->Enter();
60+
}
61+
62+
void TriggerReportNewContext(const FunctionCallbackInfo<Value>& args) {
63+
Isolate* isolate = args.GetIsolate();
64+
Local<Context> context = Context::New(isolate);
65+
Context::Scope context_scope(context);
66+
67+
node::TriggerNodeReport(
68+
isolate, "FooMessage", "BarTrigger", std::string(), Local<Value>());
69+
}
70+
4671
void init(Local<Object> exports) {
4772
NODE_SET_METHOD(exports, "triggerReport", TriggerReport);
4873
NODE_SET_METHOD(exports, "triggerReportNoIsolate", TriggerReportNoIsolate);
4974
NODE_SET_METHOD(exports, "triggerReportEnv", TriggerReportEnv);
5075
NODE_SET_METHOD(exports, "triggerReportNoEnv", TriggerReportNoEnv);
76+
NODE_SET_METHOD(exports, "triggerReportNoContext", TriggerReportNoContext);
77+
NODE_SET_METHOD(exports, "triggerReportNewContext", TriggerReportNewContext);
5178
}
5279

5380
NODE_MODULE(NODE_GYP_MODULE_NAME, init)

test/addons/report-api/test.js

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const tmpdir = require('../../common/tmpdir');
99
const binding = path.resolve(__dirname, `./build/${common.buildType}/binding`);
1010
const addon = require(binding);
1111

12-
function myAddonMain(method, hasJavaScriptFrames) {
12+
function myAddonMain(method, { hasIsolate, hasEnv }) {
1313
tmpdir.refresh();
1414
process.report.directory = tmpdir.path;
1515

@@ -19,26 +19,35 @@ function myAddonMain(method, hasJavaScriptFrames) {
1919
assert.strictEqual(reports.length, 1);
2020

2121
const report = reports[0];
22-
helper.validate(report);
22+
helper.validate(report, [
23+
['header.event', 'FooMessage'],
24+
['header.trigger', 'BarTrigger'],
25+
]);
2326

2427
const content = require(report);
25-
assert.strictEqual(content.header.event, 'FooMessage');
26-
assert.strictEqual(content.header.trigger, 'BarTrigger');
2728

2829
// Check that the javascript stack is present.
29-
if (hasJavaScriptFrames) {
30+
if (hasIsolate) {
3031
assert.strictEqual(content.javascriptStack.stack.findIndex((frame) => frame.match('myAddonMain')), 0);
3132
} else {
3233
assert.strictEqual(content.javascriptStack, undefined);
3334
}
35+
36+
if (hasEnv) {
37+
assert.strictEqual(content.header.threadId, 0);
38+
} else {
39+
assert.strictEqual(content.header.threadId, null);
40+
}
3441
}
3542

3643
const methods = [
37-
['triggerReport', true],
38-
['triggerReportNoIsolate', false],
39-
['triggerReportEnv', true],
40-
['triggerReportNoEnv', false],
44+
['triggerReport', true, true],
45+
['triggerReportNoIsolate', false, false],
46+
['triggerReportEnv', true, true],
47+
['triggerReportNoEnv', false, false],
48+
['triggerReportNoContext', true, false],
49+
['triggerReportNewContext', true, false],
4150
];
42-
for (const [method, hasJavaScriptFrames] of methods) {
43-
myAddonMain(method, hasJavaScriptFrames);
51+
for (const [method, hasIsolate, hasEnv] of methods) {
52+
myAddonMain(method, { hasIsolate, hasEnv });
4453
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy