diff --git a/src/encoding_binding.cc b/src/encoding_binding.cc index c569375383e8d9..5c07d8d5ecc8d4 100644 --- a/src/encoding_binding.cc +++ b/src/encoding_binding.cc @@ -418,15 +418,20 @@ void BindingData::DecodeUTF8(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); // list, flags CHECK_GE(args.Length(), 1); + auto isShared = args[0]->IsSharedArrayBuffer(); - if (!(args[0]->IsArrayBuffer() || args[0]->IsSharedArrayBuffer() || - args[0]->IsArrayBufferView())) { + if (!(args[0]->IsArrayBuffer() || isShared || args[0]->IsArrayBufferView())) { return node::THROW_ERR_INVALID_ARG_TYPE( env->isolate(), "The \"list\" argument must be an instance of SharedArrayBuffer, " "ArrayBuffer or ArrayBufferView."); } + if (args[0]->IsArrayBufferView()) { + Local view = args[0].As(); + isShared = view->Buffer()->IsSharedArrayBuffer(); + } + ArrayBufferViewContents buffer(args[0]); bool ignore_bom = args[1]->IsTrue(); @@ -435,6 +440,13 @@ void BindingData::DecodeUTF8(const FunctionCallbackInfo& args) { const char* data = buffer.data(); size_t length = buffer.length(); + std::unique_ptr data_copy; + if (isShared && length != 0) { + data_copy.reset(new char[length]); + memcpy(data_copy.get(), data, length); + data = data_copy.get(); + } + if (!ignore_bom && length >= 3) { if (memcmp(data, "\xEF\xBB\xBF", 3) == 0) { data += 3; diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 2778422ea4e7b7..3e79ced3f1ec76 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -567,19 +567,31 @@ void StringSlice(const FunctionCallbackInfo& args) { THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); ArrayBufferViewContents buffer(args[0]); - if (buffer.length() == 0) - return args.GetReturnValue().SetEmptyString(); + auto buffer_length = buffer.length(); + const char* data_ptr = buffer.data(); + + Local view = args[0].As(); + + if (buffer_length == 0) return args.GetReturnValue().SetEmptyString(); size_t start = 0; size_t end = 0; THROW_AND_RETURN_IF_OOB(ParseArrayIndex(env, args[1], 0, &start)); - THROW_AND_RETURN_IF_OOB(ParseArrayIndex(env, args[2], buffer.length(), &end)); - if (end < start) end = start; - THROW_AND_RETURN_IF_OOB(Just(end <= buffer.length())); + THROW_AND_RETURN_IF_OOB(ParseArrayIndex(env, args[2], buffer_length, &end)); + if (end <= start) return args.GetReturnValue().SetEmptyString(); + THROW_AND_RETURN_IF_OOB(Just(end <= buffer_length)); size_t length = end - start; + std::unique_ptr data_copy; + if (view->Buffer()->IsSharedArrayBuffer()) { + data_copy.reset(new char[length]); + memcpy(data_copy.get(), data_ptr + start, length); + data_ptr = data_copy.get(); + start = 0; + } + Local ret; - if (StringBytes::Encode(isolate, buffer.data() + start, length, encoding) + if (StringBytes::Encode(isolate, data_ptr + start, length, encoding) .ToLocal(&ret)) { args.GetReturnValue().Set(ret); }