[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: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#46896}
This commit is contained in:
parent
7d3c47f3ea
commit
8315422762
@ -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();
|
||||
|
12
test/mjsunit/regress/regress-748069.js
Normal file
12
test/mjsunit/regress/regress-748069.js
Normal file
@ -0,0 +1,12 @@
|
||||
// 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);
|
Loading…
Reference in New Issue
Block a user