Commit 92852e92 authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[Cleanup] String::GetChars() should assert against heap allocation

R=jkummerow@chromium.org

Bug: v8:8238
Change-Id: Ie28326ebe6c69e194857aed7b5d49cb8e5a40a29
Reviewed-on: https://chromium-review.googlesource.com/c/1349243Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57821}
parent 970fdf3c
......@@ -109,6 +109,7 @@ BUILTIN(StringFromCodePoint) {
isolate->factory()->NewRawTwoByteString(
static_cast<int>(one_byte_buffer.size() + two_byte_buffer.size())));
DisallowHeapAllocation no_gc;
CopyChars(result->GetChars(), one_byte_buffer.data(), one_byte_buffer.size());
CopyChars(result->GetChars() + one_byte_buffer.size(), two_byte_buffer.data(),
two_byte_buffer.size());
......@@ -467,6 +468,7 @@ V8_WARN_UNUSED_RESULT static Object* ConvertCase(
String::FlatContent flat_content = s->GetFlatContent();
DCHECK(flat_content.IsFlat());
bool has_changed_character = false;
DisallowHeapAllocation no_gc;
int index_to_first_unprocessed = FastAsciiConvert<Converter::kIsToLower>(
reinterpret_cast<char*>(result->GetChars()),
reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()),
......
......@@ -34,6 +34,7 @@ class MaybeUtf8 {
// Why copy? Well, the trace event mechanism requires null-terminated
// strings, the bytes we get from SeqOneByteString are not. buf_ is
// guaranteed to be null terminated.
DisallowHeapAllocation no_gc;
memcpy(buf_, Handle<SeqOneByteString>::cast(string)->GetChars(), len);
}
} else {
......
......@@ -664,6 +664,7 @@ MaybeHandle<String> Factory::NewStringFromUtf8(Vector<const char> string,
NewRawTwoByteString(non_ascii_start + utf16_length, pretenure), String);
// Copy ASCII portion.
DisallowHeapAllocation no_gc;
uint16_t* data = result->GetChars();
for (int i = 0; i < non_ascii_start; i++) {
*data++ = *ascii_data++;
......@@ -677,23 +678,31 @@ MaybeHandle<String> Factory::NewStringFromUtf8(Vector<const char> string,
MaybeHandle<String> Factory::NewStringFromUtf8SubString(
Handle<SeqOneByteString> str, int begin, int length,
PretenureFlag pretenure) {
const char* ascii_data =
reinterpret_cast<const char*>(str->GetChars() + begin);
int non_ascii_start = String::NonAsciiStart(ascii_data, length);
Access<UnicodeCache::Utf8Decoder> decoder(
isolate()->unicode_cache()->utf8_decoder());
int non_ascii_start;
int utf16_length = 0;
{
DisallowHeapAllocation no_gc;
const char* ascii_data =
reinterpret_cast<const char*>(str->GetChars() + begin);
non_ascii_start = String::NonAsciiStart(ascii_data, length);
if (non_ascii_start < length) {
// Non-ASCII and we need to decode.
auto non_ascii = Vector<const char>(ascii_data + non_ascii_start,
length - non_ascii_start);
decoder->Reset(non_ascii);
utf16_length = static_cast<int>(decoder->Utf16Length());
}
}
if (non_ascii_start >= length) {
// If the string is ASCII, we can just make a substring.
// TODO(v8): the pretenure flag is ignored in this case.
return NewSubString(str, begin, begin + length);
}
// Non-ASCII and we need to decode.
auto non_ascii = Vector<const char>(ascii_data + non_ascii_start,
length - non_ascii_start);
Access<UnicodeCache::Utf8Decoder> decoder(
isolate()->unicode_cache()->utf8_decoder());
decoder->Reset(non_ascii);
int utf16_length = static_cast<int>(decoder->Utf16Length());
DCHECK_GT(utf16_length, 0);
// Allocate string.
......@@ -704,9 +713,11 @@ MaybeHandle<String> Factory::NewStringFromUtf8SubString(
// Update pointer references, since the original string may have moved after
// allocation.
ascii_data = reinterpret_cast<const char*>(str->GetChars() + begin);
non_ascii = Vector<const char>(ascii_data + non_ascii_start,
length - non_ascii_start);
DisallowHeapAllocation no_gc;
const char* ascii_data =
reinterpret_cast<const char*>(str->GetChars() + begin);
auto non_ascii = Vector<const char>(ascii_data + non_ascii_start,
length - non_ascii_start);
// Copy ASCII portion.
uint16_t* data = result->GetChars();
......@@ -728,12 +739,14 @@ MaybeHandle<String> Factory::NewStringFromTwoByte(const uc16* string,
Handle<SeqOneByteString> result;
ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
NewRawOneByteString(length, pretenure), String);
DisallowHeapAllocation no_gc;
CopyChars(result->GetChars(), string, length);
return result;
} else {
Handle<SeqTwoByteString> result;
ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
NewRawTwoByteString(length, pretenure), String);
DisallowHeapAllocation no_gc;
CopyChars(result->GetChars(), string, length);
return result;
}
......@@ -828,6 +841,7 @@ Handle<String> Factory::AllocateTwoByteInternalizedString(
answer->set_length(str.length());
answer->set_hash_field(hash_field);
DCHECK_EQ(size, answer->Size());
DisallowHeapAllocation no_gc;
// Fill in the characters.
MemCopy(answer->GetChars(), str.start(), str.length() * kUC16Size);
......@@ -861,6 +875,7 @@ Handle<String> Factory::AllocateInternalizedStringImpl(T t, int chars,
answer->set_length(chars);
answer->set_hash_field(hash_field);
DCHECK_EQ(size, answer->Size());
DisallowHeapAllocation no_gc;
if (is_one_byte) {
WriteOneByteData(t, SeqOneByteString::cast(*answer)->GetChars(), chars);
......@@ -876,6 +891,7 @@ Handle<String> Factory::NewInternalizedStringFromUtf8(Vector<const char> str,
if (IsOneByte(str, chars)) {
Handle<SeqOneByteString> result =
AllocateRawOneByteInternalizedString(str.length(), hash_field);
DisallowHeapAllocation no_allocation;
MemCopy(result->GetChars(), str.start(), str.length());
return result;
}
......@@ -886,6 +902,7 @@ Handle<String> Factory::NewOneByteInternalizedString(Vector<const uint8_t> str,
uint32_t hash_field) {
Handle<SeqOneByteString> result =
AllocateRawOneByteInternalizedString(str.length(), hash_field);
DisallowHeapAllocation no_allocation;
MemCopy(result->GetChars(), str.start(), str.length());
return result;
}
......@@ -895,6 +912,7 @@ Handle<String> Factory::NewOneByteInternalizedSubString(
uint32_t hash_field) {
Handle<SeqOneByteString> result =
AllocateRawOneByteInternalizedString(length, hash_field);
DisallowHeapAllocation no_allocation;
MemCopy(result->GetChars(), string->GetChars() + offset, length);
return result;
}
......@@ -1052,6 +1070,7 @@ static inline Handle<String> MakeOrFindTwoCharacterString(Isolate* isolate,
1)); // because of this.
Handle<SeqOneByteString> str =
isolate->factory()->NewRawOneByteString(2).ToHandleChecked();
DisallowHeapAllocation no_allocation;
uint8_t* dest = str->GetChars();
dest[0] = static_cast<uint8_t>(c1);
dest[1] = static_cast<uint8_t>(c2);
......@@ -1059,6 +1078,7 @@ static inline Handle<String> MakeOrFindTwoCharacterString(Isolate* isolate,
} else {
Handle<SeqTwoByteString> str =
isolate->factory()->NewRawTwoByteString(2).ToHandleChecked();
DisallowHeapAllocation no_allocation;
uc16* dest = str->GetChars();
dest[0] = c1;
dest[1] = c2;
......@@ -1188,6 +1208,7 @@ Handle<String> Factory::NewSurrogatePairString(uint16_t lead, uint16_t trail) {
Handle<SeqTwoByteString> str =
isolate()->factory()->NewRawTwoByteString(2).ToHandleChecked();
DisallowHeapAllocation no_allocation;
uc16* dest = str->GetChars();
dest[0] = lead;
dest[1] = trail;
......@@ -1221,15 +1242,15 @@ Handle<String> Factory::NewProperSubString(Handle<String> str, int begin,
if (str->IsOneByteRepresentation()) {
Handle<SeqOneByteString> result =
NewRawOneByteString(length).ToHandleChecked();
uint8_t* dest = result->GetChars();
DisallowHeapAllocation no_gc;
uint8_t* dest = result->GetChars();
String::WriteToFlat(*str, dest, begin, end);
return result;
} else {
Handle<SeqTwoByteString> result =
NewRawTwoByteString(length).ToHandleChecked();
uc16* dest = result->GetChars();
DisallowHeapAllocation no_gc;
uc16* dest = result->GetChars();
String::WriteToFlat(*str, dest, begin, end);
return result;
}
......
......@@ -667,6 +667,7 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
int length = position_ - beg_pos;
double number;
if (seq_one_byte) {
DisallowHeapAllocation no_gc;
Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
number = StringToDouble(chars,
NO_FLAGS, // Hex, octal or trailing junk.
......@@ -726,9 +727,13 @@ Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
Handle<StringType> seq_string =
NewRawString<StringType>(factory(), length, pretenure_);
// Copy prefix into seq_str.
SinkChar* dest = seq_string->GetChars();
String::WriteToFlat(*prefix, dest, start, end);
{
DisallowHeapAllocation no_gc;
// Copy prefix into seq_str.
SinkChar* dest = seq_string->GetChars();
String::WriteToFlat(*prefix, dest, start, end);
}
while (c0_ != '"') {
// Check for control character (0x00-0x1F) or unterminated string (<0).
......@@ -879,8 +884,6 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
} else {
hash = static_cast<uint32_t>(length);
}
Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_,
length);
StringTable string_table = isolate()->heap()->string_table();
uint32_t capacity = string_table->Capacity();
uint32_t entry = StringTable::FirstProbe(hash, capacity);
......@@ -894,12 +897,16 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
factory()->InternalizeOneByteString(seq_source_, position_, length);
break;
}
if (!element->IsTheHole(isolate()) &&
String::cast(element)->IsOneByteEqualTo(string_vector)) {
result = Handle<String>(String::cast(element), isolate());
DCHECK_EQ(result->Hash(),
(hash << String::kHashShift) >> String::kHashShift);
break;
if (!element->IsTheHole(isolate())) {
DisallowHeapAllocation no_gc;
Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_,
length);
if (String::cast(element)->IsOneByteEqualTo(string_vector)) {
result = Handle<String>(String::cast(element), isolate());
DCHECK_EQ(result->Hash(),
(hash << String::kHashShift) >> String::kHashShift);
break;
}
}
entry = StringTable::NextProbe(entry, count++, capacity);
}
......@@ -929,6 +936,7 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
int length = position_ - beg_pos;
Handle<String> result =
factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
DisallowHeapAllocation no_gc;
uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
String::WriteToFlat(*source_, dest, beg_pos, position_);
......
......@@ -11382,6 +11382,7 @@ void String::WriteToFlat(String* src,
sinkchar* sink,
int f,
int t) {
DisallowHeapAllocation no_gc;
String* source = src;
int from = f;
int to = t;
......@@ -12361,6 +12362,7 @@ bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
}
uint32_t String::ComputeAndSetHash(Isolate* isolate) {
DisallowHeapAllocation no_gc;
// Should only be called if hash code has not yet been computed.
DCHECK(!HasHashCode());
......@@ -12386,6 +12388,7 @@ bool String::ComputeArrayIndex(uint32_t* index) {
bool String::SlowAsArrayIndex(uint32_t* index) {
DisallowHeapAllocation no_gc;
if (length() <= kMaxCachedArrayIndexLength) {
Hash(); // force computation of hash code
uint32_t field = hash_field();
......@@ -16751,6 +16754,7 @@ Handle<String> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
bool SeqOneByteSubStringKey::IsMatch(Object* string) {
DisallowHeapAllocation no_gc;
Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
return String::cast(string)->IsOneByteEqualTo(chars);
}
......
......@@ -239,11 +239,13 @@ class SeqOneByteSubStringKey : public StringTableKey {
#endif
SeqOneByteSubStringKey(Isolate* isolate, Handle<SeqOneByteString> string,
int from, int length)
: StringTableKey(StringHasher::HashSequentialString(
string->GetChars() + from, length, isolate->heap()->HashSeed())),
string_(string),
from_(from),
length_(length) {
: StringTableKey(0), string_(string), from_(from), length_(length) {
// We have to set the hash later.
DisallowHeapAllocation no_gc;
uint32_t hash = StringHasher::HashSequentialString(
string->GetChars() + from, length, isolate->heap()->HashSeed());
set_hash_field(hash);
DCHECK_LE(0, length_);
DCHECK_LE(from_ + length_, string_->length());
DCHECK(string_->IsSeqOneByteString());
......@@ -384,6 +386,7 @@ String* String::GetUnderlying() {
template <class Visitor>
ConsString* String::VisitFlat(Visitor* visitor, String* string,
const int offset) {
DisallowHeapAllocation no_gc;
int slice_offset = offset;
const int length = string->length();
DCHECK(offset <= length);
......@@ -474,6 +477,7 @@ Address SeqOneByteString::GetCharsAddress() {
}
uint8_t* SeqOneByteString::GetChars() {
DCHECK(!AllowHeapAllocation::IsAllowed());
return reinterpret_cast<uint8_t*>(GetCharsAddress());
}
......@@ -482,6 +486,7 @@ Address SeqTwoByteString::GetCharsAddress() {
}
uc16* SeqTwoByteString::GetChars() {
DCHECK(!AllowHeapAllocation::IsAllowed());
return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
}
......
......@@ -257,6 +257,7 @@ class BufferedCharacterStream : public Utf16CharacterStream {
buffer_start_ = &buffer_[0];
buffer_cursor_ = buffer_start_;
DisallowHeapAllocation no_gc;
Range<uint8_t> range =
byte_stream_.GetDataAt(position, runtime_call_stats());
if (range.length() == 0) {
......@@ -310,6 +311,7 @@ class UnbufferedCharacterStream : public Utf16CharacterStream {
bool ReadBlock() final {
size_t position = pos();
buffer_pos_ = position;
DisallowHeapAllocation no_gc;
Range<uint16_t> range =
byte_stream_.GetDataAt(position, runtime_call_stats());
buffer_start_ = range.start;
......
......@@ -154,6 +154,7 @@ int NativeRegExpMacroAssembler::CheckStackGuardState(
Isolate* isolate, int start_index, bool is_direct_call,
Address* return_address, Code re_code, String** subject,
const byte** input_start, const byte** input_end) {
AllowHeapAllocation allow_allocation;
DCHECK(re_code->raw_instruction_start() <= *return_address);
DCHECK(*return_address <= re_code->raw_instruction_end());
int return_value = 0;
......@@ -249,6 +250,7 @@ NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Match(
// String is now either Sequential or External
int char_size_shift = is_one_byte ? 0 : 1;
DisallowHeapAllocation no_gc;
const byte* input_start =
StringCharacterPosition(subject_ptr, start_offset + slice_offset);
int byte_length = char_length << char_size_shift;
......@@ -287,7 +289,10 @@ NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Execute(
if (result == EXCEPTION && !isolate->has_pending_exception()) {
// We detected a stack overflow (on the backtrack stack) in RegExp code,
// but haven't created the exception yet.
// but haven't created the exception yet. Additionally, we allow heap
// allocation because even though it invalidates {input_start} and
// {input_end}, we are about to return anyway.
AllowHeapAllocation allow_allocation;
isolate->StackOverflow();
}
return static_cast<Result>(result);
......
......@@ -570,6 +570,7 @@ V8_WARN_UNUSED_RESULT static Object* StringReplaceGlobalAtomRegExpWithString(
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, untyped_res, maybe_res);
Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(untyped_res);
DisallowHeapAllocation no_gc;
for (int index : *indices) {
// Copy non-matched subject content.
if (subject_pos < index) {
......@@ -739,6 +740,7 @@ V8_WARN_UNUSED_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString(
int prev = 0;
int position = 0;
DisallowHeapAllocation no_gc;
do {
start = current_match[0];
end = current_match[1];
......
......@@ -327,6 +327,7 @@ RUNTIME_FUNCTION(Runtime_StringBuilderConcat) {
Handle<SeqOneByteString> answer;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, answer, isolate->factory()->NewRawOneByteString(length));
DisallowHeapAllocation no_gc;
StringBuilderConcatHelper(*special, answer->GetChars(),
FixedArray::cast(array->elements()),
array_length);
......@@ -335,6 +336,7 @@ RUNTIME_FUNCTION(Runtime_StringBuilderConcat) {
Handle<SeqTwoByteString> answer;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, answer, isolate->factory()->NewRawTwoByteString(length));
DisallowHeapAllocation no_gc;
StringBuilderConcatHelper(*special, answer->GetChars(),
FixedArray::cast(array->elements()),
array_length);
......@@ -552,6 +554,7 @@ RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator) {
Handle<SeqOneByteString> result = isolate->factory()
->NewRawOneByteString(string_length)
.ToHandleChecked();
DisallowHeapAllocation no_gc;
JoinSparseArrayWithSeparator<uint8_t>(
FixedArray::cast(elements_array->elements()), elements_length,
array_length, *separator,
......@@ -561,6 +564,7 @@ RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator) {
Handle<SeqTwoByteString> result = isolate->factory()
->NewRawTwoByteString(string_length)
.ToHandleChecked();
DisallowHeapAllocation no_gc;
JoinSparseArrayWithSeparator<uc16>(
FixedArray::cast(elements_array->elements()), elements_length,
array_length, *separator,
......
......@@ -194,6 +194,7 @@ MaybeHandle<String> Uri::Decode(Isolate* isolate, Handle<String> uri,
isolate, result, isolate->factory()->NewRawTwoByteString(result_length),
String);
DisallowHeapAllocation no_gc;
CopyChars(result->GetChars(), one_byte_buffer.data(), one_byte_buffer.size());
CopyChars(result->GetChars() + one_byte_buffer.size(), two_byte_buffer.data(),
two_byte_buffer.size());
......
......@@ -1336,6 +1336,7 @@ MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
// Copy the bytes directly into the new string.
// Warning: this uses host endianness.
DisallowHeapAllocation no_gc;
memcpy(string->GetChars(), bytes.begin(), bytes.length());
return string;
}
......
......@@ -1787,6 +1787,7 @@ TEST(OneToTwoByteStringCopy) {
isolate->factory()->NewStringFromTwoByte(str).ToHandleChecked();
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
ft.Call(string1, string2);
DisallowHeapAllocation no_gc;
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[0],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[0]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[1],
......@@ -1818,6 +1819,7 @@ TEST(OneToOneByteStringCopy) {
isolate->factory()->NewStringFromOneByte(str).ToHandleChecked();
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
ft.Call(string1, string2);
DisallowHeapAllocation no_gc;
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[0],
Handle<SeqOneByteString>::cast(string2)->GetChars()[0]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[1],
......@@ -1849,6 +1851,7 @@ TEST(OneToOneByteStringCopyNonZeroStart) {
isolate->factory()->NewStringFromOneByte(str).ToHandleChecked();
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
ft.Call(string1, string2);
DisallowHeapAllocation no_gc;
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[0],
Handle<SeqOneByteString>::cast(string2)->GetChars()[3]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[1],
......@@ -1880,6 +1883,7 @@ TEST(TwoToTwoByteStringCopy) {
isolate->factory()->NewStringFromTwoByte(str2).ToHandleChecked();
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
ft.Call(string1, string2);
DisallowHeapAllocation no_gc;
CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars()[0],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[0]);
CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars()[1],
......
......@@ -1819,6 +1819,7 @@ TEST(Regress876759) {
{
Handle<SeqTwoByteString> raw =
factory->NewRawTwoByteString(kLength).ToHandleChecked();
DisallowHeapAllocation no_gc;
CopyChars(raw->GetChars(), two_byte_buf, kLength);
parent = raw;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment