-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
src: unify implementations of Utf8Value etc.
Unify the common code of `Utf8Value`, `TwoByteValue`, `BufferValue` and `StringBytes::InlineDecoder` into one class. Always make the result zero-terminated for the first three. This fixes two problems in passing: * When the conversion of the input value to String fails, make the buffer zero-terminated anyway. Previously, this would have resulted in possibly reading uninitialized data in multiple places in the code. An instance of that problem can be reproduced by running e.g. `valgrind node -e 'net.isIP({ toString() { throw Error() } })'`. * Previously, `BufferValue` copied one byte too much from the source, possibly resulting in an out-of-bounds memory access. This can be reproduced by running e.g. `valgrind node -e \ 'fs.openSync(Buffer.from("node".repeat(8192)), "r")'`. Further minor changes: * This lifts the `out()` method of `StringBytes::InlineDecoder` to the common class so that it can be used when using the overloaded `operator*` does not seem appropiate. * Hopefully clearer variable names. * Add checks to make sure the length of the data does not exceed the allocated storage size, including the possible null terminator. PR-URL: #6357 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Trevor Norris <[email protected]>
- Loading branch information
Showing
3 changed files
with
159 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,78 @@ | ||
#include "util.h" | ||
#include "node_buffer.h" | ||
#include "string_bytes.h" | ||
|
||
namespace node { | ||
|
||
Utf8Value::Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value) | ||
: length_(0), str_(str_st_) { | ||
// Make sure result is always zero-terminated, even if conversion to string | ||
// fails. | ||
str_st_[0] = '\0'; | ||
using v8::Isolate; | ||
using v8::Local; | ||
using v8::String; | ||
using v8::Value; | ||
|
||
template <typename T> | ||
static void MakeUtf8String(Isolate* isolate, | ||
Local<Value> value, | ||
T* target) { | ||
Local<String> string = value->ToString(isolate); | ||
if (string.IsEmpty()) | ||
return; | ||
|
||
const size_t storage = StringBytes::StorageSize(isolate, string, UTF8) + 1; | ||
target->AllocateSufficientStorage(storage); | ||
const int flags = | ||
String::NO_NULL_TERMINATION | String::REPLACE_INVALID_UTF8; | ||
const int length = string->WriteUtf8(target->out(), storage, 0, flags); | ||
target->SetLengthAndZeroTerminate(length); | ||
} | ||
|
||
Utf8Value::Utf8Value(Isolate* isolate, Local<Value> value) { | ||
if (value.IsEmpty()) | ||
return; | ||
|
||
MakeUtf8String(isolate, value, this); | ||
} | ||
|
||
|
||
TwoByteValue::TwoByteValue(Isolate* isolate, Local<Value> value) { | ||
if (value.IsEmpty()) { | ||
return; | ||
} | ||
|
||
v8::Local<v8::String> string = value->ToString(isolate); | ||
if (string.IsEmpty()) | ||
return; | ||
|
||
// Allocate enough space to include the null terminator | ||
size_t len = StringBytes::StorageSize(isolate, string, UTF8) + 1; | ||
if (len > sizeof(str_st_)) { | ||
str_ = static_cast<char*>(malloc(len)); | ||
CHECK_NE(str_, nullptr); | ||
} | ||
const size_t storage = string->Length() + 1; | ||
AllocateSufficientStorage(storage); | ||
|
||
const int flags = | ||
v8::String::NO_NULL_TERMINATION | v8::String::REPLACE_INVALID_UTF8; | ||
length_ = string->WriteUtf8(str_, len, 0, flags); | ||
str_[length_] = '\0'; | ||
String::NO_NULL_TERMINATION | String::REPLACE_INVALID_UTF8; | ||
const int length = string->Write(out(), 0, storage, flags); | ||
SetLengthAndZeroTerminate(length); | ||
} | ||
|
||
BufferValue::BufferValue(Isolate* isolate, Local<Value> value) { | ||
// Slightly different take on Utf8Value. If value is a String, | ||
// it will return a Utf8 encoded string. If value is a Buffer, | ||
// it will copy the data out of the Buffer as is. | ||
if (value.IsEmpty()) { | ||
// Dereferencing this object will return nullptr. | ||
Invalidate(); | ||
return; | ||
} | ||
|
||
if (value->IsString()) { | ||
MakeUtf8String(isolate, value, this); | ||
} else if (Buffer::HasInstance(value)) { | ||
const size_t len = Buffer::Length(value); | ||
// Leave place for the terminating '\0' byte. | ||
AllocateSufficientStorage(len + 1); | ||
memcpy(out(), Buffer::Data(value), len); | ||
SetLengthAndZeroTerminate(len); | ||
} else { | ||
Invalidate(); | ||
} | ||
} | ||
|
||
} // namespace node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters