src,stream: remove *Check*()
calls from non-Initialize()
functions
There is no need to crash the process if any of these checks fail. Signed-off-by: Darshan Sen <darshan.sen@postman.com> PR-URL: https://github.com/nodejs/node/pull/40425 Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
7ed303beba
commit
516cdcd8aa
@ -149,9 +149,11 @@ int StreamBase::Shutdown(v8::Local<v8::Object> req_wrap_obj) {
|
|||||||
|
|
||||||
const char* msg = Error();
|
const char* msg = Error();
|
||||||
if (msg != nullptr) {
|
if (msg != nullptr) {
|
||||||
req_wrap_obj->Set(
|
if (req_wrap_obj->Set(env->context(),
|
||||||
env->context(),
|
env->error_string(),
|
||||||
env->error_string(), OneByteString(env->isolate(), msg)).Check();
|
OneByteString(env->isolate(), msg)).IsNothing()) {
|
||||||
|
return UV_EBUSY;
|
||||||
|
}
|
||||||
ClearError();
|
ClearError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,9 +205,11 @@ StreamWriteResult StreamBase::Write(
|
|||||||
|
|
||||||
const char* msg = Error();
|
const char* msg = Error();
|
||||||
if (msg != nullptr) {
|
if (msg != nullptr) {
|
||||||
req_wrap_obj->Set(env->context(),
|
if (req_wrap_obj->Set(env->context(),
|
||||||
env->error_string(),
|
env->error_string(),
|
||||||
OneByteString(env->isolate(), msg)).Check();
|
OneByteString(env->isolate(), msg)).IsNothing()) {
|
||||||
|
return StreamWriteResult { false, UV_EBUSY, nullptr, 0, {} };
|
||||||
|
}
|
||||||
ClearError();
|
ClearError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,10 +283,12 @@ void StreamReq::Done(int status, const char* error_str) {
|
|||||||
Environment* env = async_wrap->env();
|
Environment* env = async_wrap->env();
|
||||||
if (error_str != nullptr) {
|
if (error_str != nullptr) {
|
||||||
v8::HandleScope handle_scope(env->isolate());
|
v8::HandleScope handle_scope(env->isolate());
|
||||||
async_wrap->object()->Set(env->context(),
|
if (async_wrap->object()->Set(
|
||||||
env->error_string(),
|
env->context(),
|
||||||
OneByteString(env->isolate(), error_str))
|
env->error_string(),
|
||||||
.Check();
|
OneByteString(env->isolate(), error_str)).IsNothing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OnDone(status);
|
OnDone(status);
|
||||||
|
@ -106,23 +106,30 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) {
|
|||||||
if (!all_buffers) {
|
if (!all_buffers) {
|
||||||
// Determine storage size first
|
// Determine storage size first
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
Local<Value> chunk = chunks->Get(context, i * 2).ToLocalChecked();
|
Local<Value> chunk;
|
||||||
|
if (!chunks->Get(context, i * 2).ToLocal(&chunk))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (Buffer::HasInstance(chunk))
|
if (Buffer::HasInstance(chunk))
|
||||||
continue;
|
continue;
|
||||||
// Buffer chunk, no additional storage required
|
// Buffer chunk, no additional storage required
|
||||||
|
|
||||||
// String chunk
|
// String chunk
|
||||||
Local<String> string = chunk->ToString(context).ToLocalChecked();
|
Local<String> string;
|
||||||
enum encoding encoding = ParseEncoding(isolate,
|
if (!chunk->ToString(context).ToLocal(&string))
|
||||||
chunks->Get(context, i * 2 + 1).ToLocalChecked());
|
return -1;
|
||||||
|
Local<Value> next_chunk;
|
||||||
|
if (!chunks->Get(context, i * 2 + 1).ToLocal(&next_chunk))
|
||||||
|
return -1;
|
||||||
|
enum encoding encoding = ParseEncoding(isolate, next_chunk);
|
||||||
size_t chunk_size;
|
size_t chunk_size;
|
||||||
if (encoding == UTF8 && string->Length() > 65535 &&
|
if ((encoding == UTF8 &&
|
||||||
!StringBytes::Size(isolate, string, encoding).To(&chunk_size))
|
string->Length() > 65535 &&
|
||||||
return 0;
|
!StringBytes::Size(isolate, string, encoding).To(&chunk_size)) ||
|
||||||
else if (!StringBytes::StorageSize(isolate, string, encoding)
|
!StringBytes::StorageSize(isolate, string, encoding)
|
||||||
.To(&chunk_size))
|
.To(&chunk_size)) {
|
||||||
return 0;
|
return -1;
|
||||||
|
}
|
||||||
storage_size += chunk_size;
|
storage_size += chunk_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +137,9 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) {
|
|||||||
return UV_ENOBUFS;
|
return UV_ENOBUFS;
|
||||||
} else {
|
} else {
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
Local<Value> chunk = chunks->Get(context, i).ToLocalChecked();
|
Local<Value> chunk;
|
||||||
|
if (!chunks->Get(context, i).ToLocal(&chunk))
|
||||||
|
return -1;
|
||||||
bufs[i].base = Buffer::Data(chunk);
|
bufs[i].base = Buffer::Data(chunk);
|
||||||
bufs[i].len = Buffer::Length(chunk);
|
bufs[i].len = Buffer::Length(chunk);
|
||||||
}
|
}
|
||||||
@ -145,7 +154,9 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) {
|
|||||||
offset = 0;
|
offset = 0;
|
||||||
if (!all_buffers) {
|
if (!all_buffers) {
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
Local<Value> chunk = chunks->Get(context, i * 2).ToLocalChecked();
|
Local<Value> chunk;
|
||||||
|
if (!chunks->Get(context, i * 2).ToLocal(&chunk))
|
||||||
|
return -1;
|
||||||
|
|
||||||
// Write buffer
|
// Write buffer
|
||||||
if (Buffer::HasInstance(chunk)) {
|
if (Buffer::HasInstance(chunk)) {
|
||||||
@ -160,9 +171,13 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) {
|
|||||||
static_cast<char*>(bs ? bs->Data() : nullptr) + offset;
|
static_cast<char*>(bs ? bs->Data() : nullptr) + offset;
|
||||||
size_t str_size = (bs ? bs->ByteLength() : 0) - offset;
|
size_t str_size = (bs ? bs->ByteLength() : 0) - offset;
|
||||||
|
|
||||||
Local<String> string = chunk->ToString(context).ToLocalChecked();
|
Local<String> string;
|
||||||
enum encoding encoding = ParseEncoding(isolate,
|
if (!chunk->ToString(context).ToLocal(&string))
|
||||||
chunks->Get(context, i * 2 + 1).ToLocalChecked());
|
return -1;
|
||||||
|
Local<Value> next_chunk;
|
||||||
|
if (!chunks->Get(context, i * 2 + 1).ToLocal(&next_chunk))
|
||||||
|
return -1;
|
||||||
|
enum encoding encoding = ParseEncoding(isolate, next_chunk);
|
||||||
str_size = StringBytes::Write(isolate,
|
str_size = StringBytes::Write(isolate,
|
||||||
str_storage,
|
str_storage,
|
||||||
str_size,
|
str_size,
|
||||||
@ -207,9 +222,11 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo<Value>& args) {
|
|||||||
send_handle = reinterpret_cast<uv_stream_t*>(wrap->GetHandle());
|
send_handle = reinterpret_cast<uv_stream_t*>(wrap->GetHandle());
|
||||||
// Reference LibuvStreamWrap instance to prevent it from being garbage
|
// Reference LibuvStreamWrap instance to prevent it from being garbage
|
||||||
// collected before `AfterWrite` is called.
|
// collected before `AfterWrite` is called.
|
||||||
req_wrap_obj->Set(env->context(),
|
if (req_wrap_obj->Set(env->context(),
|
||||||
env->handle_string(),
|
env->handle_string(),
|
||||||
send_handle_obj).Check();
|
send_handle_obj).IsNothing()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamWriteResult res = Write(&buf, 1, send_handle, req_wrap_obj);
|
StreamWriteResult res = Write(&buf, 1, send_handle, req_wrap_obj);
|
||||||
@ -236,12 +253,12 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) {
|
|||||||
// For UTF8 strings that are very long, go ahead and take the hit for
|
// For UTF8 strings that are very long, go ahead and take the hit for
|
||||||
// computing their actual size, rather than tripling the storage.
|
// computing their actual size, rather than tripling the storage.
|
||||||
size_t storage_size;
|
size_t storage_size;
|
||||||
if (enc == UTF8 && string->Length() > 65535 &&
|
if ((enc == UTF8 &&
|
||||||
!StringBytes::Size(isolate, string, enc).To(&storage_size))
|
string->Length() > 65535 &&
|
||||||
return 0;
|
!StringBytes::Size(isolate, string, enc).To(&storage_size)) ||
|
||||||
else if (!StringBytes::StorageSize(isolate, string, enc)
|
!StringBytes::StorageSize(isolate, string, enc).To(&storage_size)) {
|
||||||
.To(&storage_size))
|
return -1;
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
if (storage_size > INT_MAX)
|
if (storage_size > INT_MAX)
|
||||||
return UV_ENOBUFS;
|
return UV_ENOBUFS;
|
||||||
@ -312,9 +329,11 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) {
|
|||||||
send_handle = reinterpret_cast<uv_stream_t*>(wrap->GetHandle());
|
send_handle = reinterpret_cast<uv_stream_t*>(wrap->GetHandle());
|
||||||
// Reference LibuvStreamWrap instance to prevent it from being garbage
|
// Reference LibuvStreamWrap instance to prevent it from being garbage
|
||||||
// collected before `AfterWrite` is called.
|
// collected before `AfterWrite` is called.
|
||||||
req_wrap_obj->Set(env->context(),
|
if (req_wrap_obj->Set(env->context(),
|
||||||
env->handle_string(),
|
env->handle_string(),
|
||||||
send_handle_obj).Check();
|
send_handle_obj).IsNothing()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamWriteResult res = Write(&buf, 1, send_handle, req_wrap_obj);
|
StreamWriteResult res = Write(&buf, 1, send_handle, req_wrap_obj);
|
||||||
|
@ -49,6 +49,8 @@ class StreamReq {
|
|||||||
virtual AsyncWrap* GetAsyncWrap() = 0;
|
virtual AsyncWrap* GetAsyncWrap() = 0;
|
||||||
inline v8::Local<v8::Object> object();
|
inline v8::Local<v8::Object> object();
|
||||||
|
|
||||||
|
// TODO(RaisinTen): Update the return type to a Maybe, so that we can indicate
|
||||||
|
// if there is a pending exception/termination.
|
||||||
inline void Done(int status, const char* error_str = nullptr);
|
inline void Done(int status, const char* error_str = nullptr);
|
||||||
inline void Dispose();
|
inline void Dispose();
|
||||||
|
|
||||||
@ -326,6 +328,8 @@ class StreamBase : public StreamResource {
|
|||||||
// subclasses are also `BaseObject`s.
|
// subclasses are also `BaseObject`s.
|
||||||
Environment* stream_env() const { return env_; }
|
Environment* stream_env() const { return env_; }
|
||||||
|
|
||||||
|
// TODO(RaisinTen): Update the return type to a Maybe, so that we can indicate
|
||||||
|
// if there is a pending exception/termination.
|
||||||
// Shut down the current stream. This request can use an existing
|
// Shut down the current stream. This request can use an existing
|
||||||
// ShutdownWrap object (that was created in JS), or a new one will be created.
|
// ShutdownWrap object (that was created in JS), or a new one will be created.
|
||||||
// Returns 1 in case of a synchronous completion, 0 in case of asynchronous
|
// Returns 1 in case of a synchronous completion, 0 in case of asynchronous
|
||||||
@ -333,6 +337,8 @@ class StreamBase : public StreamResource {
|
|||||||
inline int Shutdown(
|
inline int Shutdown(
|
||||||
v8::Local<v8::Object> req_wrap_obj = v8::Local<v8::Object>());
|
v8::Local<v8::Object> req_wrap_obj = v8::Local<v8::Object>());
|
||||||
|
|
||||||
|
// TODO(RaisinTen): Update the return type to a Maybe, so that we can indicate
|
||||||
|
// if there is a pending exception/termination.
|
||||||
// Write data to the current stream. This request can use an existing
|
// Write data to the current stream. This request can use an existing
|
||||||
// WriteWrap object (that was created in JS), or a new one will be created.
|
// WriteWrap object (that was created in JS), or a new one will be created.
|
||||||
// This will first try to write synchronously using `DoTryWrite()`, then
|
// This will first try to write synchronously using `DoTryWrite()`, then
|
||||||
|
@ -33,14 +33,26 @@ StreamPipe::StreamPipe(StreamBase* source,
|
|||||||
// In particular, this makes sure that they are garbage collected as a group,
|
// In particular, this makes sure that they are garbage collected as a group,
|
||||||
// if that applies to the given streams (for example, Http2Streams use
|
// if that applies to the given streams (for example, Http2Streams use
|
||||||
// weak references).
|
// weak references).
|
||||||
obj->Set(env()->context(), env()->source_string(), source->GetObject())
|
if (obj->Set(env()->context(),
|
||||||
.Check();
|
env()->source_string(),
|
||||||
source->GetObject()->Set(env()->context(), env()->pipe_target_string(), obj)
|
source->GetObject()).IsNothing()) {
|
||||||
.Check();
|
return;
|
||||||
obj->Set(env()->context(), env()->sink_string(), sink->GetObject())
|
}
|
||||||
.Check();
|
if (source->GetObject()->Set(env()->context(),
|
||||||
sink->GetObject()->Set(env()->context(), env()->pipe_source_string(), obj)
|
env()->pipe_target_string(),
|
||||||
.Check();
|
obj).IsNothing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (obj->Set(env()->context(),
|
||||||
|
env()->sink_string(),
|
||||||
|
sink->GetObject()).IsNothing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sink->GetObject()->Set(env()->context(),
|
||||||
|
env()->pipe_source_string(),
|
||||||
|
obj).IsNothing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamPipe::~StreamPipe() {
|
StreamPipe::~StreamPipe() {
|
||||||
@ -172,7 +184,8 @@ void StreamPipe::WritableListener::OnStreamAfterWrite(WriteWrap* w,
|
|||||||
Environment* env = pipe->env();
|
Environment* env = pipe->env();
|
||||||
HandleScope handle_scope(env->isolate());
|
HandleScope handle_scope(env->isolate());
|
||||||
Context::Scope context_scope(env->context());
|
Context::Scope context_scope(env->context());
|
||||||
pipe->MakeCallback(env->oncomplete_string(), 0, nullptr).ToLocalChecked();
|
if (pipe->MakeCallback(env->oncomplete_string(), 0, nullptr).IsEmpty())
|
||||||
|
return;
|
||||||
stream()->RemoveStreamListener(this);
|
stream()->RemoveStreamListener(this);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -9,11 +9,14 @@ namespace node {
|
|||||||
|
|
||||||
class StreamPipe : public AsyncWrap {
|
class StreamPipe : public AsyncWrap {
|
||||||
public:
|
public:
|
||||||
StreamPipe(StreamBase* source, StreamBase* sink, v8::Local<v8::Object> obj);
|
|
||||||
~StreamPipe() override;
|
~StreamPipe() override;
|
||||||
|
|
||||||
void Unpipe(bool is_in_deletion = false);
|
void Unpipe(bool is_in_deletion = false);
|
||||||
|
|
||||||
|
// TODO(RaisinTen): Just like MessagePort, add the following overload:
|
||||||
|
// static StreamPipe* New(StreamBase* source, StreamBase* sink,
|
||||||
|
// v8::Local<v8::Object> obj);
|
||||||
|
// so that we can indicate if there is a pending exception/termination.
|
||||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void Unpipe(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void Unpipe(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
@ -25,6 +28,8 @@ class StreamPipe : public AsyncWrap {
|
|||||||
SET_SELF_SIZE(StreamPipe)
|
SET_SELF_SIZE(StreamPipe)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
StreamPipe(StreamBase* source, StreamBase* sink, v8::Local<v8::Object> obj);
|
||||||
|
|
||||||
inline StreamBase* source();
|
inline StreamBase* source();
|
||||||
inline StreamBase* sink();
|
inline StreamBase* sink();
|
||||||
|
|
||||||
|
@ -268,12 +268,12 @@ void LibuvStreamWrap::OnUvRead(ssize_t nread, const uv_buf_t* buf) {
|
|||||||
CHECK_EQ(type, UV_UNKNOWN_HANDLE);
|
CHECK_EQ(type, UV_UNKNOWN_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pending_obj.IsEmpty()) {
|
Local<Object> local_pending_obj;
|
||||||
object()
|
if (pending_obj.ToLocal(&local_pending_obj) &&
|
||||||
->Set(env()->context(),
|
object()->Set(env()->context(),
|
||||||
env()->pending_handle_string(),
|
env()->pending_handle_string(),
|
||||||
pending_obj.ToLocalChecked())
|
local_pending_obj).IsNothing()) {
|
||||||
.Check();
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +105,8 @@ class LibuvStreamWrap : public HandleWrap, public StreamBase {
|
|||||||
|
|
||||||
// Callbacks for libuv
|
// Callbacks for libuv
|
||||||
void OnUvAlloc(size_t suggested_size, uv_buf_t* buf);
|
void OnUvAlloc(size_t suggested_size, uv_buf_t* buf);
|
||||||
|
// TODO(RaisinTen): Update the return type to a Maybe, so that we can indicate
|
||||||
|
// if there is a pending exception/termination.
|
||||||
void OnUvRead(ssize_t nread, const uv_buf_t* buf);
|
void OnUvRead(ssize_t nread, const uv_buf_t* buf);
|
||||||
|
|
||||||
static void AfterUvWrite(uv_write_t* req, int status);
|
static void AfterUvWrite(uv_write_t* req, int status);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user