Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Unified Diff: src/runtime.cc

Issue 525064: Fixed potential length miscalculations by limiting max size of arrays and strings. (Closed)
Patch Set: Added (unrelated) cast to make Win64 compile. Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.cc ('k') | src/utils.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index 50ea60f055de29afa5138cfc8dee75d4ddcad2c3..76ea4bb7ee0110fc6ecc2d536192a09c5f3723fa 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -5371,8 +5371,8 @@ class ArrayConcatVisitor {
fast_elements_(fast_elements), index_offset_(0) { }
void visit(uint32_t i, Handle<Object> elm) {
- uint32_t index = i + index_offset_;
- if (index >= index_limit_) return;
+ if (i >= index_limit_ - index_offset_) return;
+ uint32_t index = index_offset_ + i;
if (fast_elements_) {
ASSERT(index < static_cast<uint32_t>(storage_->length()));
@@ -5388,16 +5388,23 @@ class ArrayConcatVisitor {
}
void increase_index_offset(uint32_t delta) {
- index_offset_ += delta;
+ if (index_limit_ - index_offset_ < delta) {
+ index_offset_ = index_limit_;
+ } else {
+ index_offset_ += delta;
+ }
}
Handle<FixedArray> storage() { return storage_; }
private:
Handle<FixedArray> storage_;
+ // Limit on the accepted indices. Elements with indices larger than the
+ // limit are ignored by the visitor.
uint32_t index_limit_;
- bool fast_elements_;
+ // Index after last seen index. Always less than or equal to index_limit_.
uint32_t index_offset_;
+ bool fast_elements_;
};
@@ -5569,6 +5576,11 @@ static uint32_t IterateElements(Handle<JSObject> receiver,
*
* If a ArrayConcatVisitor object is given, the visitor is called with
* parameters, element's index + visitor_index_offset and the element.
+ *
+ * The returned number of elements is an upper bound on the actual number
+ * of elements added. If the same element occurs in more than one object
+ * in the array's prototype chain, it will be counted more than once, but
+ * will only occur once in the result.
*/
static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array,
ArrayConcatVisitor* visitor) {
@@ -5591,8 +5603,14 @@ static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array,
uint32_t nof_elements = 0;
for (int i = objects.length() - 1; i >= 0; i--) {
Handle<JSObject> obj = objects[i];
- nof_elements +=
+ uint32_t encountered_elements =
IterateElements(Handle<JSObject>::cast(obj), range, visitor);
+
+ if (encountered_elements > JSObject::kMaxElementCount - nof_elements) {
+ nof_elements = JSObject::kMaxElementCount;
+ } else {
+ nof_elements += encountered_elements;
+ }
}
return nof_elements;
@@ -5609,13 +5627,16 @@ static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array,
* elements. If an argument is not an Array object, the function
* visits the object as if it is an one-element array.
*
- * If the result array index overflows 32-bit integer, the rounded
+ * If the result array index overflows 32-bit unsigned integer, the rounded
* non-negative number is used as new length. For example, if one
* array length is 2^32 - 1, second array length is 1, the
* concatenated array length is 0.
+ * TODO(lrn) Change length behavior to ECMAScript 5 specification (length
+ * is one more than the last array index to get a value assigned).
*/
static uint32_t IterateArguments(Handle<JSArray> arguments,
ArrayConcatVisitor* visitor) {
+ const uint32_t max_length = JSObject::kMaxElementCount;
uint32_t visited_elements = 0;
uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
@@ -5628,16 +5649,23 @@ static uint32_t IterateArguments(Handle<JSArray> arguments,
IterateArrayAndPrototypeElements(array, visitor);
// Total elements of array and its prototype chain can be more than
// the array length, but ArrayConcat can only concatenate at most
- // the array length number of elements.
- visited_elements += (nof_elements > len) ? len : nof_elements;
+ // the array length number of elements. We use the length as an estimate
+ // for the actual number of elements added.
+ uint32_t added_elements = (nof_elements > len) ? len : nof_elements;
+ if (JSArray::kMaxElementCount - visited_elements < added_elements) {
+ visited_elements = JSArray::kMaxElementCount;
+ } else {
+ visited_elements += added_elements;
+ }
if (visitor) visitor->increase_index_offset(len);
-
} else {
if (visitor) {
visitor->visit(0, obj);
visitor->increase_index_offset(1);
}
- visited_elements++;
+ if (visited_elements < JSArray::kMaxElementCount) {
+ visited_elements++;
+ }
}
}
return visited_elements;
@@ -5647,6 +5675,8 @@ static uint32_t IterateArguments(Handle<JSArray> arguments,
/**
* Array::concat implementation.
* See ECMAScript 262, 15.4.4.4.
+ * TODO(lrn): Fix non-compliance for very large concatenations and update to
+ * following the ECMAScript 5 specification.
*/
static Object* Runtime_ArrayConcat(Arguments args) {
ASSERT(args.length() == 1);
@@ -5663,12 +5693,18 @@ static Object* Runtime_ArrayConcat(Arguments args) {
{ AssertNoAllocation nogc;
for (uint32_t i = 0; i < num_of_args; i++) {
Object* obj = arguments->GetElement(i);
+ uint32_t length_estimate;
if (obj->IsJSArray()) {
- result_length +=
+ length_estimate =
static_cast<uint32_t>(JSArray::cast(obj)->length()->Number());
} else {
- result_length++;
+ length_estimate = 1;
+ }
+ if (JSObject::kMaxElementCount - result_length < length_estimate) {
+ result_length = JSObject::kMaxElementCount;
+ break;
}
+ result_length += length_estimate;
}
}
« no previous file with comments | « src/objects.cc ('k') | src/utils.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698