Commit 9d493179 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[bigint] Fix NoSideEffectsToString for 32-bit platforms

On 32-bit platforms, String::kMaxLength is such that not all BigInts
can be converted to Strings. NoSideEffectsToString, however, used to
assume that this conversion always succeeds. This patch adds a check
for the failure case, and returns "<a very large BigInt>" instead of
crashing.
This change is practically unobservable, because actually formatting
such a huge BigInt to String would take "forever", which is also why
there is no regression test.

Bug: chromium:876628
Change-Id: I1eacdc1cce753ac5d9ca66e61e479043ab576e07
Reviewed-on: https://chromium-review.googlesource.com/1194004Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55491}
parent c85128fd
......@@ -367,8 +367,17 @@ Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
Handle<Object> input) {
DisallowJavascriptExecution no_js(isolate);
if (input->IsString() || input->IsNumeric() || input->IsOddball()) {
if (input->IsString() || input->IsNumber() || input->IsOddball()) {
return Object::ToString(isolate, input).ToHandleChecked();
} else if (input->IsBigInt()) {
MaybeHandle<String> maybe_string =
BigInt::ToString(isolate, Handle<BigInt>::cast(input), 10, kDontThrow);
Handle<String> result;
if (maybe_string.ToHandle(&result)) return result;
// BigInt-to-String conversion can fail on 32-bit platforms where
// String::kMaxLength is too small to fit this BigInt.
return isolate->factory()->NewStringFromStaticChars(
"<a very large BigInt>");
} else if (input->IsFunction()) {
// -- F u n c t i o n
Handle<String> fun_str;
......
......@@ -155,9 +155,11 @@ class MutableBigInt : public FreshlyAllocatedBigInt,
static MaybeHandle<String> ToStringBasePowerOfTwo(Isolate* isolate,
Handle<BigIntBase> x,
int radix);
int radix,
ShouldThrow should_throw);
static MaybeHandle<String> ToStringGeneric(Isolate* isolate,
Handle<BigIntBase> x, int radix);
Handle<BigIntBase> x, int radix,
ShouldThrow should_throw);
static double ToDouble(Handle<BigIntBase> x);
enum Rounding { kRoundDown, kTie, kRoundUp };
......@@ -924,14 +926,15 @@ ComparisonResult BigInt::CompareToDouble(Handle<BigInt> x, double y) {
}
MaybeHandle<String> BigInt::ToString(Isolate* isolate, Handle<BigInt> bigint,
int radix) {
int radix, ShouldThrow should_throw) {
if (bigint->is_zero()) {
return isolate->factory()->NewStringFromStaticChars("0");
}
if (base::bits::IsPowerOfTwo(radix)) {
return MutableBigInt::ToStringBasePowerOfTwo(isolate, bigint, radix);
return MutableBigInt::ToStringBasePowerOfTwo(isolate, bigint, radix,
should_throw);
}
return MutableBigInt::ToStringGeneric(isolate, bigint, radix);
return MutableBigInt::ToStringGeneric(isolate, bigint, radix, should_throw);
}
MaybeHandle<BigInt> BigInt::FromNumber(Isolate* isolate,
......@@ -1924,9 +1927,9 @@ MaybeHandle<BigInt> BigInt::FromSerializedDigits(
static const char kConversionChars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
MaybeHandle<String> MutableBigInt::ToStringBasePowerOfTwo(Isolate* isolate,
Handle<BigIntBase> x,
int radix) {
MaybeHandle<String> MutableBigInt::ToStringBasePowerOfTwo(
Isolate* isolate, Handle<BigIntBase> x, int radix,
ShouldThrow should_throw) {
STATIC_ASSERT(base::bits::IsPowerOfTwo(kDigitBits));
DCHECK(base::bits::IsPowerOfTwo(radix));
DCHECK(radix >= 2 && radix <= 32);
......@@ -1945,7 +1948,11 @@ MaybeHandle<String> MutableBigInt::ToStringBasePowerOfTwo(Isolate* isolate,
(bit_length + bits_per_char - 1) / bits_per_char + sign;
if (chars_required > String::kMaxLength) {
THROW_NEW_ERROR(isolate, NewInvalidStringLengthError(), String);
if (should_throw == kThrowOnError) {
THROW_NEW_ERROR(isolate, NewInvalidStringLengthError(), String);
} else {
return MaybeHandle<String>();
}
}
Handle<SeqOneByteString> result =
......@@ -1988,7 +1995,8 @@ MaybeHandle<String> MutableBigInt::ToStringBasePowerOfTwo(Isolate* isolate,
MaybeHandle<String> MutableBigInt::ToStringGeneric(Isolate* isolate,
Handle<BigIntBase> x,
int radix) {
int radix,
ShouldThrow should_throw) {
DCHECK(radix >= 2 && radix <= 36);
DCHECK(!x->is_zero());
Heap* heap = isolate->heap();
......@@ -2014,7 +2022,11 @@ MaybeHandle<String> MutableBigInt::ToStringGeneric(Isolate* isolate,
chars_required += sign;
if (chars_required > String::kMaxLength) {
THROW_NEW_ERROR(isolate, NewInvalidStringLengthError(), String);
if (should_throw == kThrowOnError) {
THROW_NEW_ERROR(isolate, NewInvalidStringLengthError(), String);
} else {
return MaybeHandle<String>();
}
}
Handle<SeqOneByteString> result =
isolate->factory()
......
......@@ -173,7 +173,8 @@ class V8_EXPORT_PRIVATE BigInt : public BigIntBase {
}
static MaybeHandle<String> ToString(Isolate* isolate, Handle<BigInt> bigint,
int radix = 10);
int radix = 10,
ShouldThrow should_throw = kThrowOnError);
// "The Number value for x", see:
// https://tc39.github.io/ecma262/#sec-ecmascript-language-types-number-type
// Returns a Smi or HeapNumber.
......
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