From 4b7d5dc4bbebb3444b002c176357f584b17709b7 Mon Sep 17 00:00:00 2001 From: yangguo Date: Fri, 19 Jun 2015 01:31:22 -0700 Subject: [PATCH] Protect error message formatter against invalid string length. R=mstarzinger@chromium.org BUG=chromium:500980 LOG=N Review URL: https://codereview.chromium.org/1191263002 Cr-Commit-Position: refs/heads/master@{#29135} --- src/messages.cc | 13 ++++++++++++- src/string-builder.cc | 20 ++++++++------------ src/string-builder.h | 2 +- test/mjsunit/regress/regress-500980.js | 7 +++++++ 4 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 test/mjsunit/regress/regress-500980.js diff --git a/src/messages.cc b/src/messages.cc index ce6375594..a69df0463 100644 --- a/src/messages.cc +++ b/src/messages.cc @@ -331,6 +331,7 @@ MaybeHandle MessageTemplate::FormatMessage(int template_index, Handle arg0, Handle arg1, Handle arg2) { + static const int kMaxArgLength = 256; Isolate* isolate = arg0->GetIsolate(); const char* template_string; switch (template_index) { @@ -358,7 +359,17 @@ MaybeHandle MessageTemplate::FormatMessage(int template_index, builder.AppendCharacter('%'); } else { DCHECK(i < arraysize(args)); - builder.AppendString(args[i++]); + Handle arg = args[i++]; + int length = arg->length(); + if (length > kMaxArgLength) { + builder.AppendString( + isolate->factory()->NewSubString(arg, 0, kMaxArgLength - 6)); + builder.AppendCString("..."); + builder.AppendString( + isolate->factory()->NewSubString(arg, length - 3, length)); + } else { + builder.AppendString(arg); + } } } else { builder.AppendCharacter(*c); diff --git a/src/string-builder.cc b/src/string-builder.cc index c7488abb9..7c46e0d52 100644 --- a/src/string-builder.cc +++ b/src/string-builder.cc @@ -55,25 +55,23 @@ IncrementalStringBuilder::IncrementalStringBuilder(Isolate* isolate) } -void IncrementalStringBuilder::Accumulate() { - // Only accumulate fully written strings. Shrink first if necessary. - DCHECK_EQ(current_index_, current_part()->length()); +void IncrementalStringBuilder::Accumulate(Handle new_part) { Handle new_accumulator; - if (accumulator()->length() + current_part()->length() > String::kMaxLength) { + if (accumulator()->length() + new_part->length() > String::kMaxLength) { // Set the flag and carry on. Delay throwing the exception till the end. new_accumulator = factory()->empty_string(); overflowed_ = true; } else { - new_accumulator = factory() - ->NewConsString(accumulator(), current_part()) - .ToHandleChecked(); + new_accumulator = + factory()->NewConsString(accumulator(), new_part).ToHandleChecked(); } set_accumulator(new_accumulator); } void IncrementalStringBuilder::Extend() { - Accumulate(); + DCHECK_EQ(current_index_, current_part()->length()); + Accumulate(current_part()); if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { part_length_ *= kPartLengthGrowthFactor; } @@ -91,7 +89,7 @@ void IncrementalStringBuilder::Extend() { MaybeHandle IncrementalStringBuilder::Finish() { ShrinkCurrentPart(); - Accumulate(); + Accumulate(current_part()); if (overflowed_) { THROW_NEW_ERROR(isolate_, NewInvalidStringLengthError(), String); } @@ -103,9 +101,7 @@ void IncrementalStringBuilder::AppendString(Handle string) { ShrinkCurrentPart(); part_length_ = kInitialPartLength; // Allocate conservatively. Extend(); // Attach current part and allocate new part. - Handle concat = - factory()->NewConsString(accumulator(), string).ToHandleChecked(); - set_accumulator(concat); + Accumulate(string); } } // namespace internal } // namespace v8 diff --git a/src/string-builder.h b/src/string-builder.h index 43b690dba..531466532 100644 --- a/src/string-builder.h +++ b/src/string-builder.h @@ -384,7 +384,7 @@ class IncrementalStringBuilder { } // Add the current part to the accumulator. - void Accumulate(); + void Accumulate(Handle new_part); // Finish the current part and allocate a new part. void Extend(); diff --git a/test/mjsunit/regress/regress-500980.js b/test/mjsunit/regress/regress-500980.js new file mode 100644 index 000000000..841d26aa4 --- /dev/null +++ b/test/mjsunit/regress/regress-500980.js @@ -0,0 +1,7 @@ +// Copyright 2015 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. + +var a = "a"; +assertThrows(function() { while (true) a += a; }, RangeError); +assertThrows(function() { a in a; }, TypeError); -- 2.34.1