Commit 83154227 authored by Peter Marshall's avatar Peter Marshall Committed by Commit Bot

[runtime] Check for overflow when serializing Strings for JSON.

Previously we would shift the length of the string by three, which
could overflow with the new larger string length limit. Now we check
that the length will fit without extra allocation before and after
the shift, because really large strings will never fit, and will
always go to the Checked case.

Bug: chromium:748069, v8:6148
Change-Id: I41cac14b0fde6c5e8ca92305a052cbb743111554
Reviewed-on: https://chromium-review.googlesource.com/584611
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46896}
parent 7d3c47f3
......@@ -635,12 +635,9 @@ template <typename SrcChar, typename DestChar>
void JsonStringifier::SerializeString_(Handle<String> string) {
int length = string->length();
builder_.Append<uint8_t, DestChar>('"');
// We make a rough estimate to find out if the current string can be
// serialized without allocating a new string part. The worst case length of
// an escaped character is 6. Shifting the remainin string length right by 3
// is a more pessimistic estimate, but faster to calculate.
int worst_case_length = length << 3;
if (builder_.CurrentPartCanFit(worst_case_length)) {
// We might be able to fit the whole escaped string in the current string
// part, or we might need to allocate.
if (int worst_case_length = builder_.EscapedLengthIfCurrentPartFits(length)) {
DisallowHeapAllocation no_gc;
Vector<const SrcChar> vector = string->GetCharVector<SrcChar>();
IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend(
......@@ -657,7 +654,6 @@ void JsonStringifier::SerializeString_(Handle<String> string) {
}
}
}
builder_.Append<uint8_t, DestChar>('"');
}
......
......@@ -304,6 +304,19 @@ class IncrementalStringBuilder {
return part_length_ - current_index_ > length;
}
// We make a rough estimate to find out if the current string can be
// serialized without allocating a new string part. The worst case length of
// an escaped character is 6. Shifting the remaining string length right by 3
// is a more pessimistic estimate, but faster to calculate.
INLINE(int EscapedLengthIfCurrentPartFits(int length)) {
if (length > kMaxPartLength) return 0;
STATIC_ASSERT((kMaxPartLength << 3) <= String::kMaxLength);
// This shift will not overflow because length is already less than the
// maximum part length.
int worst_case_length = length << 3;
return CurrentPartCanFit(worst_case_length) ? worst_case_length : 0;
}
void AppendString(Handle<String> string);
MaybeHandle<String> Finish();
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
try {
var a = 'a'.repeat(1 << 28);
} catch (e) {
// If the allocation fails, we don't care, because we can't cause the
// overflow.
}
// Cause an overflow in worst-case calculation for string replacement.
JSON.stringify(a);
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