Commit 61fefb19 authored by Adam Klein's avatar Adam Klein Committed by Commit Bot

[bigint] Restrict the length of literals in the scanner

The parser now throws for literals that are too big for the runtime
to support, thus avoiding CHECK-failures further down the line.

Tbr: rmcilroy@chromium.org
Bug: v8:6791
Change-Id: Ie45ddebb8aa9e7a30e8b6b74f99916b700e38e4a
Reviewed-on: https://chromium-review.googlesource.com/747682
Commit-Queue: Adam Klein <adamk@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49059}
parent dbcea115
......@@ -834,6 +834,8 @@ Handle<Object> Literal::BuildValue(Isolate* isolate) const {
case kTheHole:
return isolate->factory()->the_hole_value();
case kBigInt:
// This should never fail: the parser will never create a BigInt
// literal that cannot be allocated.
return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
}
UNREACHABLE();
......
......@@ -381,8 +381,8 @@ Handle<Object> ConstantArrayBuilder::Entry::ToHandle(Isolate* isolate) const {
case Tag::kHeapNumber:
return isolate->factory()->NewNumber(heap_number_);
case Tag::kBigInt:
// TODO(adamk): Don't check-fail on conversion failure; instead
// check for errors during parsing and throw at that point.
// This should never fail: the parser will never create a BigInt
// literal that cannot be allocated.
return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
case Tag::kScope:
return scope_->scope_info();
......
......@@ -89,7 +89,8 @@ class V8_EXPORT_PRIVATE BigInt : public HeapObject {
// kMaxInt / kDigitBits. However, we use a lower limit for now, because
// raising it later is easier than lowering it.
// Support up to 1 million bits.
static const int kMaxLength = 1024 * 1024 / (kPointerSize * kBitsPerByte);
static const int kMaxLengthBits = 1024 * 1024;
static const int kMaxLength = kMaxLengthBits / (kPointerSize * kBitsPerByte);
class BodyDescriptor;
......@@ -190,9 +191,9 @@ class V8_EXPORT_PRIVATE BigInt : public HeapObject {
return static_cast<digit_t>(~x) == 0;
}
static const int kMaxLengthBits = 20;
STATIC_ASSERT(kMaxLength <= ((1 << kMaxLengthBits) - 1));
class LengthBits : public BitField<int, 0, kMaxLengthBits> {};
static const int kLengthFieldBits = 20;
STATIC_ASSERT(kMaxLength <= ((1 << kLengthFieldBits) - 1));
class LengthBits : public BitField<int, 0, kLengthFieldBits> {};
class SignBits : public BitField<bool, LengthBits::kNext, 1> {};
// Low-level accessors.
......
......@@ -13,6 +13,7 @@
#include "src/ast/ast-value-factory.h"
#include "src/char-predicates-inl.h"
#include "src/conversions-inl.h"
#include "src/objects/bigint.h"
#include "src/parsing/duplicate-finder.h" // For Scanner::FindSymbol
#include "src/unicode-cache-inl.h"
......@@ -1333,6 +1334,17 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
bool is_bigint = false;
if (allow_harmony_bigint() && c0_ == 'n' && !seen_period &&
(kind == DECIMAL || kind == HEX || kind == OCTAL || kind == BINARY)) {
// Check that the literal is within our limits for BigInt length.
// For simplicity, use 4 bits per character to calculate the maximum
// allowed literal length.
static const int kMaxBigIntCharacters = BigInt::kMaxLengthBits / 4;
int length = source_pos() - start_pos - (kind != DECIMAL ? 2 : 0);
if (length > kMaxBigIntCharacters) {
ReportScannerError(Location(start_pos, source_pos()),
MessageTemplate::kBigIntTooBig);
return Token::ILLEGAL;
}
is_bigint = true;
Advance();
} else if (c0_ == 'e' || c0_ == 'E') {
......@@ -1365,6 +1377,7 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
octal_pos_ = Location(start_pos, source_pos());
octal_message_ = MessageTemplate::kStrictDecimalWithLeadingZero;
}
return is_bigint ? Token::BIGINT : Token::NUMBER;
}
......
......@@ -667,10 +667,6 @@ class Scanner {
bool is_literal_one_byte() const {
return !current_.literal_chars || current_.literal_chars->is_one_byte();
}
int literal_length() const {
if (current_.literal_chars) return current_.literal_chars->length();
return Token::StringLength(current_.token);
}
// Returns the literal string for the next token (the token that
// would be returned if Next() were called).
Vector<const uint8_t> next_literal_one_byte_string() const {
......
// 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.
//
// Flags: --harmony-bigint --no-opt
const MAX_BIGINT_BITS = 1024 * 1024; // Matches BigInt::kMaxLengthBits
const MAX_BIGINT_CHARS = MAX_BIGINT_BITS / 4;
const TOO_MANY_ONES = Array(MAX_BIGINT_CHARS + 2).join("1") + "n";
const tooBigHex = "0x" + TOO_MANY_ONES;
assertThrows(tooBigHex, SyntaxError);
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