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 { ...@@ -834,6 +834,8 @@ Handle<Object> Literal::BuildValue(Isolate* isolate) const {
case kTheHole: case kTheHole:
return isolate->factory()->the_hole_value(); return isolate->factory()->the_hole_value();
case kBigInt: 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(); return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
} }
UNREACHABLE(); UNREACHABLE();
......
...@@ -381,8 +381,8 @@ Handle<Object> ConstantArrayBuilder::Entry::ToHandle(Isolate* isolate) const { ...@@ -381,8 +381,8 @@ Handle<Object> ConstantArrayBuilder::Entry::ToHandle(Isolate* isolate) const {
case Tag::kHeapNumber: case Tag::kHeapNumber:
return isolate->factory()->NewNumber(heap_number_); return isolate->factory()->NewNumber(heap_number_);
case Tag::kBigInt: case Tag::kBigInt:
// TODO(adamk): Don't check-fail on conversion failure; instead // This should never fail: the parser will never create a BigInt
// check for errors during parsing and throw at that point. // literal that cannot be allocated.
return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked(); return BigIntLiteral(isolate, bigint_.c_str()).ToHandleChecked();
case Tag::kScope: case Tag::kScope:
return scope_->scope_info(); return scope_->scope_info();
......
...@@ -89,7 +89,8 @@ class V8_EXPORT_PRIVATE BigInt : public HeapObject { ...@@ -89,7 +89,8 @@ class V8_EXPORT_PRIVATE BigInt : public HeapObject {
// kMaxInt / kDigitBits. However, we use a lower limit for now, because // kMaxInt / kDigitBits. However, we use a lower limit for now, because
// raising it later is easier than lowering it. // raising it later is easier than lowering it.
// Support up to 1 million bits. // 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; class BodyDescriptor;
...@@ -190,9 +191,9 @@ class V8_EXPORT_PRIVATE BigInt : public HeapObject { ...@@ -190,9 +191,9 @@ class V8_EXPORT_PRIVATE BigInt : public HeapObject {
return static_cast<digit_t>(~x) == 0; return static_cast<digit_t>(~x) == 0;
} }
static const int kMaxLengthBits = 20; static const int kLengthFieldBits = 20;
STATIC_ASSERT(kMaxLength <= ((1 << kMaxLengthBits) - 1)); STATIC_ASSERT(kMaxLength <= ((1 << kLengthFieldBits) - 1));
class LengthBits : public BitField<int, 0, kMaxLengthBits> {}; class LengthBits : public BitField<int, 0, kLengthFieldBits> {};
class SignBits : public BitField<bool, LengthBits::kNext, 1> {}; class SignBits : public BitField<bool, LengthBits::kNext, 1> {};
// Low-level accessors. // Low-level accessors.
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "src/ast/ast-value-factory.h" #include "src/ast/ast-value-factory.h"
#include "src/char-predicates-inl.h" #include "src/char-predicates-inl.h"
#include "src/conversions-inl.h" #include "src/conversions-inl.h"
#include "src/objects/bigint.h"
#include "src/parsing/duplicate-finder.h" // For Scanner::FindSymbol #include "src/parsing/duplicate-finder.h" // For Scanner::FindSymbol
#include "src/unicode-cache-inl.h" #include "src/unicode-cache-inl.h"
...@@ -1333,6 +1334,17 @@ Token::Value Scanner::ScanNumber(bool seen_period) { ...@@ -1333,6 +1334,17 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
bool is_bigint = false; bool is_bigint = false;
if (allow_harmony_bigint() && c0_ == 'n' && !seen_period && if (allow_harmony_bigint() && c0_ == 'n' && !seen_period &&
(kind == DECIMAL || kind == HEX || kind == OCTAL || kind == BINARY)) { (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; is_bigint = true;
Advance(); Advance();
} else if (c0_ == 'e' || c0_ == 'E') { } else if (c0_ == 'e' || c0_ == 'E') {
...@@ -1365,6 +1377,7 @@ Token::Value Scanner::ScanNumber(bool seen_period) { ...@@ -1365,6 +1377,7 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
octal_pos_ = Location(start_pos, source_pos()); octal_pos_ = Location(start_pos, source_pos());
octal_message_ = MessageTemplate::kStrictDecimalWithLeadingZero; octal_message_ = MessageTemplate::kStrictDecimalWithLeadingZero;
} }
return is_bigint ? Token::BIGINT : Token::NUMBER; return is_bigint ? Token::BIGINT : Token::NUMBER;
} }
......
...@@ -667,10 +667,6 @@ class Scanner { ...@@ -667,10 +667,6 @@ class Scanner {
bool is_literal_one_byte() const { bool is_literal_one_byte() const {
return !current_.literal_chars || current_.literal_chars->is_one_byte(); 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 // Returns the literal string for the next token (the token that
// would be returned if Next() were called). // would be returned if Next() were called).
Vector<const uint8_t> next_literal_one_byte_string() const { 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