Skip to content

Commit

Permalink
Merged: [turbofan] Protect against overflow of node id and input inde…
Browse files Browse the repository at this point in the history
…x field

Revision: 35d8b9a

BUG=chromium:1003286
LOG=N
NOTRY=true
NOPRESUBMIT=true
NOTREECHECKS=true
[email protected]

Change-Id: Icdf6e132f3a7b39ae8532f878923e373500d3f33
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1820937
Reviewed-by: Michael Stanton <[email protected]>
Commit-Queue: Georg Neis <[email protected]>
Cr-Commit-Position: refs/branch-heads/7.8@{v8#14}
Cr-Branched-From: 73694fd-refs/heads/7.8.279@{#1}
Cr-Branched-From: 2314928-refs/heads/master@{#63555}
  • Loading branch information
GeorgNeis authored and Commit Bot committed Sep 24, 2019
1 parent 3d0c8ac commit d65841e
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 11 deletions.
7 changes: 4 additions & 3 deletions src/compiler/graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ Node* Graph::CloneNode(const Node* node) {


NodeId Graph::NextNodeId() {
NodeId const id = next_node_id_;
CHECK(!base::bits::UnsignedAddOverflow32(id, 1, &next_node_id_));
return id;
// A node's id is internally stored in a bit field using fewer bits than
// NodeId (see Node::IdField). Hence the addition below won't ever overflow.
DCHECK_LT(next_node_id_, std::numeric_limits<NodeId>::max());
return next_node_id_++;
}

void Graph::Print() const { StdoutStream{} << AsRPO(*this); }
Expand Down
20 changes: 16 additions & 4 deletions src/compiler/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ Node::OutOfLineInputs* Node::OutOfLineInputs::New(Zone* zone, int capacity) {

void Node::OutOfLineInputs::ExtractFrom(Use* old_use_ptr, Node** old_input_ptr,
int count) {
DCHECK_GE(count, 0);
// Extract the inputs from the old use and input pointers and copy them
// to this out-of-line-storage.
Use* new_use_ptr = reinterpret_cast<Use*>(this) - 1;
Node** new_input_ptr = inputs();
CHECK_IMPLIES(count > 0, Use::InputIndexField::is_valid(count - 1));
for (int current = 0; current < count; current++) {
new_use_ptr->bit_field_ =
Use::InputIndexField::encode(current) | Use::InlineField::encode(false);
Expand All @@ -51,6 +53,8 @@ void Node::OutOfLineInputs::ExtractFrom(Use* old_use_ptr, Node** old_input_ptr,

Node* Node::New(Zone* zone, NodeId id, const Operator* op, int input_count,
Node* const* inputs, bool has_extensible_inputs) {
DCHECK_GE(input_count, 0);

Node** input_ptr;
Use* use_ptr;
Node* node;
Expand Down Expand Up @@ -102,6 +106,8 @@ Node* Node::New(Zone* zone, NodeId id, const Operator* op, int input_count,
}

// Initialize the input pointers and the uses.
CHECK_IMPLIES(input_count > 0,
Use::InputIndexField::is_valid(input_count - 1));
for (int current = 0; current < input_count; ++current) {
Node* to = *inputs++;
input_ptr[current] = to;
Expand Down Expand Up @@ -137,19 +143,20 @@ void Node::AppendInput(Zone* zone, Node* new_to) {
DCHECK_NOT_NULL(zone);
DCHECK_NOT_NULL(new_to);

int inline_count = InlineCountField::decode(bit_field_);
int inline_capacity = InlineCapacityField::decode(bit_field_);
int const inline_count = InlineCountField::decode(bit_field_);
int const inline_capacity = InlineCapacityField::decode(bit_field_);
if (inline_count < inline_capacity) {
// Append inline input.
bit_field_ = InlineCountField::update(bit_field_, inline_count + 1);
*GetInputPtr(inline_count) = new_to;
Use* use = GetUsePtr(inline_count);
STATIC_ASSERT(InlineCapacityField::kMax <= Use::InputIndexField::kMax);
use->bit_field_ = Use::InputIndexField::encode(inline_count) |
Use::InlineField::encode(true);
new_to->AppendUse(use);
} else {
// Append out-of-line input.
int input_count = InputCount();
int const input_count = InputCount();
OutOfLineInputs* outline = nullptr;
if (inline_count != kOutlineMarker) {
// switch to out of line inputs.
Expand All @@ -172,6 +179,7 @@ void Node::AppendInput(Zone* zone, Node* new_to) {
outline->count_++;
*GetInputPtr(input_count) = new_to;
Use* use = GetUsePtr(input_count);
CHECK(Use::InputIndexField::is_valid(input_count));
use->bit_field_ = Use::InputIndexField::encode(input_count) |
Use::InlineField::encode(false);
new_to->AppendUse(use);
Expand Down Expand Up @@ -336,9 +344,13 @@ Node::Node(NodeId id, const Operator* op, int inline_count, int inline_capacity)
bit_field_(IdField::encode(id) | InlineCountField::encode(inline_count) |
InlineCapacityField::encode(inline_capacity)),
first_use_(nullptr) {
// Check that the id didn't overflow.
STATIC_ASSERT(IdField::kMax < std::numeric_limits<NodeId>::max());
CHECK(IdField::is_valid(id));

// Inputs must either be out of line or within the inline capacity.
DCHECK_GE(kMaxInlineCapacity, inline_capacity);
DCHECK(inline_count == kOutlineMarker || inline_count <= inline_capacity);
DCHECK_LE(inline_capacity, kMaxInlineCapacity);
}


Expand Down
5 changes: 1 addition & 4 deletions src/compiler/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,7 @@ class V8_EXPORT_PRIVATE Node final {
}

using InlineField = BitField<bool, 0, 1>;
using InputIndexField = BitField<unsigned, 1, 17>;
// Leaving some space in the bitset in case we ever decide to record
// the output index.
using InputIndexField = BitField<unsigned, 1, 31>;
};

//============================================================================
Expand Down Expand Up @@ -291,7 +289,6 @@ class V8_EXPORT_PRIVATE Node final {
using InlineCountField = BitField<unsigned, 24, 4>;
using InlineCapacityField = BitField<unsigned, 28, 4>;
static const int kOutlineMarker = InlineCountField::kMax;
static const int kMaxInlineCount = InlineCountField::kMax - 1;
static const int kMaxInlineCapacity = InlineCapacityField::kMax - 1;

const Operator* op_;
Expand Down

0 comments on commit d65841e

Please sign in to comment.