Files
sdk/runtime/lib/array.cc
T
turnidge@google.com 8b68d343c7 Enforce length/size limits for variable size heap object in order to
avoid overflow.

For each variable size heap object, compute the maximum number of
elements and use that in the ::New functions to avoid overflow.  If a
bad length/size reaches a ::New function, that is a FATAL error -- the
problem should have been caught earlier by the dart api or by the
library code.

Add "border guards" in the dart api and in library calls which cause
new variable size heap objects to be allocated.  We check for invalid
length/size and throw explanatory error messages.
Review URL: https://chromiumcodereview.appspot.com//10782016

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@10130 260f80e4-7a28-3924-810f-c04153c831b5
2012-08-01 18:22:30 +00:00

112 lines
3.9 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/assert.h"
#include "vm/bootstrap_natives.h"
#include "vm/assembler.h"
#include "vm/bigint_operations.h"
#include "vm/exceptions.h"
#include "vm/native_entry.h"
#include "vm/object.h"
namespace dart {
DEFINE_NATIVE_ENTRY(ObjectArray_allocate, 2) {
const AbstractTypeArguments& type_arguments =
AbstractTypeArguments::CheckedHandle(arguments->At(0));
ASSERT(type_arguments.IsNull() ||
(type_arguments.IsInstantiated() && (type_arguments.Length() == 1)));
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(1));
intptr_t len = length.Value();
if (len < 0 || len > Array::kMaxElements) {
const String& error = String::Handle(String::NewFormatted(
"length (%ld) must be in the range [0..%ld]",
len, Array::kMaxElements));
GrowableArray<const Object*> args;
args.Add(&error);
Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
}
const Array& new_array = Array::Handle(Array::New(length.Value()));
new_array.SetTypeArguments(type_arguments);
arguments->SetReturn(new_array);
}
DEFINE_NATIVE_ENTRY(ObjectArray_getIndexed, 2) {
const Array& array = Array::CheckedHandle(arguments->At(0));
GET_NATIVE_ARGUMENT(Smi, index, arguments->At(1));
if ((index.Value() < 0) || (index.Value() >= array.Length())) {
GrowableArray<const Object*> arguments;
arguments.Add(&index);
Exceptions::ThrowByType(Exceptions::kIndexOutOfRange, arguments);
}
const Instance& obj = Instance::CheckedHandle(array.At(index.Value()));
arguments->SetReturn(obj);
}
DEFINE_NATIVE_ENTRY(ObjectArray_setIndexed, 3) {
const Array& array = Array::CheckedHandle(arguments->At(0));
GET_NATIVE_ARGUMENT(Smi, index, arguments->At(1));
const Instance& value = Instance::CheckedHandle(arguments->At(2));
if ((index.Value() < 0) || (index.Value() >= array.Length())) {
GrowableArray<const Object*> arguments;
arguments.Add(&index);
Exceptions::ThrowByType(Exceptions::kIndexOutOfRange, arguments);
}
array.SetAt(index.Value(), value);
}
DEFINE_NATIVE_ENTRY(ObjectArray_getLength, 1) {
const Array& array = Array::CheckedHandle(arguments->At(0));
const Smi& length = Smi::Handle(Smi::New(array.Length()));
arguments->SetReturn(length);
}
// ObjectArray src, int srcStart, int dstStart, int count.
DEFINE_NATIVE_ENTRY(ObjectArray_copyFromObjectArray, 5) {
const Array& dest = Array::CheckedHandle(arguments->At(0));
GET_NATIVE_ARGUMENT(Array, source, arguments->At(1));
GET_NATIVE_ARGUMENT(Smi, src_start, arguments->At(2));
GET_NATIVE_ARGUMENT(Smi, dst_start, arguments->At(3));
GET_NATIVE_ARGUMENT(Smi, count, arguments->At(4));
intptr_t icount = count.Value();
if (icount < 0) {
GrowableArray<const Object*> args;
Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
}
if (icount == 0) {
return;
}
intptr_t isrc_start = src_start.Value();
intptr_t idst_start = dst_start.Value();
if ((isrc_start < 0) || ((isrc_start + icount) > source.Length())) {
GrowableArray<const Object*> arguments;
arguments.Add(&src_start);
Exceptions::ThrowByType(Exceptions::kIndexOutOfRange, arguments);
}
if ((idst_start < 0) || ((idst_start + icount) > dest.Length())) {
GrowableArray<const Object*> arguments;
arguments.Add(&dst_start);
Exceptions::ThrowByType(Exceptions::kIndexOutOfRange, arguments);
}
Object& src_obj = Object::Handle();
if (isrc_start < idst_start) {
for (intptr_t i = icount - 1; i >= 0; i--) {
src_obj = source.At(isrc_start + i);
dest.SetAt(idst_start + i, src_obj);
}
} else {
for (intptr_t i = 0; i < icount; i++) {
src_obj = source.At(isrc_start + i);
dest.SetAt(idst_start + i, src_obj);
}
}
}
} // namespace dart