Skip to content

Commit 7707494

Browse files
committed
src: harden JSStream callbacks
Since these are executing JS code, and in particular parts of that code may be provided by userland, handle such exceptions in C++. Ref: nodejs#17938 (comment)
1 parent b171adc commit 7707494

File tree

2 files changed

+62
-13
lines changed

2 files changed

+62
-13
lines changed

src/js_stream.cc

+43-13
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ using v8::FunctionCallbackInfo;
1414
using v8::FunctionTemplate;
1515
using v8::HandleScope;
1616
using v8::Local;
17-
using v8::MaybeLocal;
1817
using v8::Object;
1918
using v8::String;
19+
using v8::TryCatch;
2020
using v8::Value;
2121

2222

@@ -87,24 +87,40 @@ bool JSStream::IsAlive() {
8787
bool JSStream::IsClosing() {
8888
HandleScope scope(env()->isolate());
8989
Context::Scope context_scope(env()->context());
90-
return MakeCallback(env()->isclosing_string(), 0, nullptr)
91-
.ToLocalChecked()->IsTrue();
90+
TryCatch try_catch(env()->isolate());
91+
Local<Value> value;
92+
if (!MakeCallback(env()->isclosing_string(), 0, nullptr).ToLocal(&value)) {
93+
FatalException(env()->isolate(), try_catch);
94+
}
95+
return value->IsTrue();
9296
}
9397

9498

9599
int JSStream::ReadStart() {
96100
HandleScope scope(env()->isolate());
97101
Context::Scope context_scope(env()->context());
98-
return MakeCallback(env()->onreadstart_string(), 0, nullptr)
99-
.ToLocalChecked()->Int32Value();
102+
TryCatch try_catch(env()->isolate());
103+
Local<Value> value;
104+
int value_int = 0;
105+
if (!MakeCallback(env()->onreadstart_string(), 0, nullptr).ToLocal(&value) ||
106+
!value->Int32Value(env()->context()).To(&value_int)) {
107+
FatalException(env()->isolate(), try_catch);
108+
}
109+
return value_int;
100110
}
101111

102112

103113
int JSStream::ReadStop() {
104114
HandleScope scope(env()->isolate());
105115
Context::Scope context_scope(env()->context());
106-
return MakeCallback(env()->onreadstop_string(), 0, nullptr)
107-
.ToLocalChecked()->Int32Value();
116+
TryCatch try_catch(env()->isolate());
117+
Local<Value> value;
118+
int value_int = 0;
119+
if (!MakeCallback(env()->onreadstop_string(), 0, nullptr).ToLocal(&value) ||
120+
!value->Int32Value(env()->context()).To(&value_int)) {
121+
FatalException(env()->isolate(), try_catch);
122+
}
123+
return value_int;
108124
}
109125

110126

@@ -117,10 +133,17 @@ int JSStream::DoShutdown(ShutdownWrap* req_wrap) {
117133
};
118134

119135
req_wrap->Dispatched();
120-
MaybeLocal<Value> res =
121-
MakeCallback(env()->onshutdown_string(), arraysize(argv), argv);
122136

123-
return res.ToLocalChecked()->Int32Value();
137+
TryCatch try_catch(env()->isolate());
138+
Local<Value> value;
139+
int value_int = 0;
140+
if (!MakeCallback(env()->onshutdown_string(),
141+
arraysize(argv),
142+
argv).ToLocal(&value) ||
143+
!value->Int32Value(env()->context()).To(&value_int)) {
144+
FatalException(env()->isolate(), try_catch);
145+
}
146+
return value_int;
124147
}
125148

126149

@@ -146,10 +169,17 @@ int JSStream::DoWrite(WriteWrap* w,
146169
};
147170

148171
w->Dispatched();
149-
MaybeLocal<Value> res =
150-
MakeCallback(env()->onwrite_string(), arraysize(argv), argv);
151172

152-
return res.ToLocalChecked()->Int32Value();
173+
TryCatch try_catch(env()->isolate());
174+
Local<Value> value;
175+
int value_int = 0;
176+
if (!MakeCallback(env()->onwrite_string(),
177+
arraysize(argv),
178+
argv).ToLocal(&value) ||
179+
!value->Int32Value(env()->context()).To(&value_int)) {
180+
FatalException(env()->isolate(), try_catch);
181+
}
182+
return value_int;
153183
}
154184

155185

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const JSStreamWrap = require('internal/wrap_js_stream');
6+
const { Duplex } = require('stream');
7+
8+
process.once('uncaughtException', common.mustCall((err) => {
9+
assert.strictEqual(err.message, 'exception!');
10+
}));
11+
12+
const socket = new JSStreamWrap(new Duplex({
13+
read: common.mustCall(),
14+
write: common.mustCall((buffer, data, cb) => {
15+
throw new Error('exception!');
16+
})
17+
}));
18+
19+
socket.end('foo');

0 commit comments

Comments
 (0)