diff --git a/src/v8_typed_array.cc b/src/v8_typed_array.cc index 1d2ffc4af75..576194f584c 100644 --- a/src/v8_typed_array.cc +++ b/src/v8_typed_array.cc @@ -131,7 +131,7 @@ class ArrayBuffer { static v8::Handle slice(const v8::Arguments& args) { if (args.Length() < 1) - return ThrowError("Wrong number of arguments."); + return ThrowTypeError("Not enough arguments"); unsigned int length = args.This()->Get(v8::String::New("byteLength"))->Uint32Value(); @@ -217,7 +217,6 @@ class TypedArray { v8::Local default_signature = v8::Signature::New(ft_cache); static BatchedMethods methods[] = { - { "get", &TypedArray::get }, { "set", &TypedArray::set }, { "slice", &TypedArray::subarray }, { "subarray", &TypedArray::subarray }, @@ -350,77 +349,63 @@ class TypedArray { return args.This(); } - static v8::Handle get(const v8::Arguments& args) { - if (args.Length() < 1) - return ThrowError("Wrong number of arguments."); - - if (args[0]->IsNumber()) - return args.This()->Get(args[0]->Uint32Value()); - - return v8::Undefined(); - } - static v8::Handle set(const v8::Arguments& args) { if (args.Length() < 1) - return ThrowError("Wrong number of arguments."); - - //if (!args[0]->IsObject()) - // return ThrowTypeError("Type error."); - - if (args[0]->IsNumber()) { // index, value - args.This()->Set(args[0]->Uint32Value(), args[1]); - } else if (args[0]->IsObject()) { - v8::Handle obj = v8::Handle::Cast(args[0]); - - if (TypedArray::HasInstance(obj)) { // ArrayBufferView. - if (args[1]->Int32Value() < 0) - return ThrowRangeError("Offset may not be negative."); - - unsigned int offset = args[1]->Uint32Value(); - unsigned int src_length = - obj->Get(v8::String::New("length"))->Uint32Value(); - unsigned int dst_length = - args.This()->Get(v8::String::New("length"))->Uint32Value(); - if (offset > dst_length) - return ThrowRangeError("Offset out of range."); - - if (src_length > dst_length - offset) - return ThrowRangeError("Offset/length out of range."); - - // We don't want to get the buffer pointer, because that means we'll have - // to just do the calculations for byteOffset / byteLength again. - // Instead just use the pointer on the external array data. - void* src_ptr = obj->GetIndexedPropertiesExternalArrayData(); - void* dst_ptr = args.This()->GetIndexedPropertiesExternalArrayData(); - - // From the spec: - // If the input array is a TypedArray, the two arrays may use the same - // underlying ArrayBuffer. In this situation, setting the values takes - // place as if all the data is first copied into a temporary buffer that - // does not overlap either of the arrays, and then the data from the - // temporary buffer is copied into the current array. - memmove(reinterpret_cast(dst_ptr) + offset * TBytes, src_ptr, - src_length * TBytes); - } else { // type[] - if (args[1]->Int32Value() < 0) - return ThrowRangeError("Offset may not be negative."); - - unsigned int src_length = - obj->Get(v8::String::New("length"))->Uint32Value(); - unsigned int dst_length = - args.This()->Get(v8::String::New("length"))->Uint32Value(); - unsigned int offset = args[1]->Uint32Value(); - - if (offset > dst_length) - return ThrowRangeError("Offset out of range."); - - if (src_length > dst_length - offset) - return ThrowRangeError("Offset/length out of range."); - - for (uint32_t i = 0; i < src_length; ++i) { - // Use the v8 setter to deal with typing. Maybe slow? - args.This()->Set(i + offset, obj->Get(i)); - } + return ThrowTypeError("Not enough arguments"); + + if (!args[0]->IsObject()) + return ThrowTypeError("Invalid argument"); + + v8::Handle obj = v8::Handle::Cast(args[0]); + + if (TypedArray::HasInstance(obj)) { // ArrayBufferView. + if (args[1]->Int32Value() < 0) + return ThrowRangeError("Offset may not be negative."); + + unsigned int offset = args[1]->Uint32Value(); + unsigned int src_length = + obj->Get(v8::String::New("length"))->Uint32Value(); + unsigned int dst_length = + args.This()->Get(v8::String::New("length"))->Uint32Value(); + if (offset > dst_length) + return ThrowRangeError("Offset out of range."); + + if (src_length > dst_length - offset) + return ThrowRangeError("Index is out of range."); + + // We don't want to get the buffer pointer, because that means we'll have + // to just do the calculations for byteOffset / byteLength again. + // Instead just use the pointer on the external array data. + void* src_ptr = obj->GetIndexedPropertiesExternalArrayData(); + void* dst_ptr = args.This()->GetIndexedPropertiesExternalArrayData(); + + // From the spec: + // If the input array is a TypedArray, the two arrays may use the same + // underlying ArrayBuffer. In this situation, setting the values takes + // place as if all the data is first copied into a temporary buffer that + // does not overlap either of the arrays, and then the data from the + // temporary buffer is copied into the current array. + memmove(reinterpret_cast(dst_ptr) + offset * TBytes, src_ptr, + src_length * TBytes); + } else { // type[] + if (args[1]->Int32Value() < 0) + return ThrowRangeError("Offset may not be negative."); + + unsigned int src_length = + obj->Get(v8::String::New("length"))->Uint32Value(); + unsigned int dst_length = + args.This()->Get(v8::String::New("length"))->Uint32Value(); + unsigned int offset = args[1]->Uint32Value(); + + if (offset > dst_length) + return ThrowRangeError("Offset out of range."); + + if (src_length > dst_length - offset) + return ThrowRangeError("Index is out of range."); + + for (uint32_t i = 0; i < src_length; ++i) { + // Use the v8 setter to deal with typing. Maybe slow? + args.This()->Set(i + offset, obj->Get(i)); } } @@ -439,11 +424,11 @@ class TypedArray { if (begin < 0) begin = length + begin; if (begin < 0) begin = 0; - if ((unsigned)begin > length) begin = length; + if (static_cast(begin) > length) begin = length; if (end < 0) end = length + end; if (end < 0) end = 0; - if ((unsigned)end > length) end = length; + if (static_cast(end) > length) end = length; if (begin > end) begin = end; @@ -617,7 +602,7 @@ class DataView { return ThrowTypeError("Constructor cannot be called as a function."); if (args.Length() < 1) - return ThrowError("Wrong number of arguments."); + return ThrowTypeError("Not enough arguments"); if (!args[0]->IsObject()) return ThrowError("Object must be an ArrayBuffer."); @@ -631,16 +616,16 @@ class DataView { unsigned int byte_offset = args[1]->Uint32Value(); if (args[1]->Int32Value() < 0 || byte_offset >= byte_length) - return ThrowRangeError("byteOffset out of range."); + return ThrowRangeError("Size is too large (or is negative)."); if (!args[2]->IsUndefined()) { if (args[2]->Int32Value() < 0) - return ThrowRangeError("byteLength out of range."); + return ThrowRangeError("Size is too large (or is negative)."); unsigned int new_byte_length = args[2]->Uint32Value(); if (new_byte_length > byte_length) - return ThrowRangeError("byteLength out of range."); + return ThrowRangeError("Size is too large (or is negative)."); if (byte_offset + new_byte_length > byte_length) - return ThrowRangeError("byteOffset/byteLength out of range."); + return ThrowRangeError("Size is too large (or is negative)."); byte_length = new_byte_length; } else { // Adjust the original byte_length from total length to length to end. @@ -669,7 +654,7 @@ class DataView { template static v8::Handle getGeneric(const v8::Arguments& args) { if (args.Length() < 1) - return ThrowError("Wrong number of arguments."); + return ThrowTypeError("Not enough arguments"); unsigned int index = args[0]->Uint32Value(); bool little_endian = args[1]->BooleanValue(); @@ -679,8 +664,10 @@ class DataView { int size = args.This()->GetIndexedPropertiesExternalArrayDataLength() * element_size; - if (index + sizeof(T) > (unsigned)size) // TODO(deanm): integer overflow. - return ThrowError("Index out of range."); + if (size <= 0 || static_cast(size) < sizeof(T) || + index > static_cast(size) - sizeof(T)) { + return ThrowError("IndexSizeError: DOM Exception 1"); + } void* ptr = reinterpret_cast( args.This()->GetIndexedPropertiesExternalArrayData()) + index; @@ -701,7 +688,7 @@ class DataView { template static v8::Handle setGeneric(const v8::Arguments& args) { if (args.Length() < 2) - return ThrowError("Wrong number of arguments."); + return ThrowTypeError("Not enough arguments"); unsigned int index = args[0]->Int32Value(); bool little_endian = args[2]->BooleanValue(); @@ -711,8 +698,10 @@ class DataView { int size = args.This()->GetIndexedPropertiesExternalArrayDataLength() * element_size; - if (index + sizeof(T) > (unsigned)size) // TODO(deanm): integer overflow. - return ThrowError("Index out of range."); + if (size <= 0 || static_cast(size) < sizeof(T) || + index > static_cast(size) - sizeof(T)) { + return ThrowError("IndexSizeError: DOM Exception 1"); + } void* ptr = reinterpret_cast( args.This()->GetIndexedPropertiesExternalArrayData()) + index; diff --git a/test/simple/test-typed-arrays.js b/test/simple/test-typed-arrays.js index 00bf613543a..78a153a7a03 100644 --- a/test/simple/test-typed-arrays.js +++ b/test/simple/test-typed-arrays.js @@ -153,13 +153,13 @@ sub[1] = 0x34; assert.equal(uint8[2], 0x12); assert.equal(uint8[3], 0x34); -// test .set(index, value), .set(arr, offset) and .get(index) -uint8.set(1, 0x09); +// test .set(index, value), .set(arr, offset) +uint8[1] = 0x09; uint8.set([0x0a, 0x0b], 2); -assert.equal(uint8.get(1), 0x09); -assert.equal(uint8.get(2), 0x0a); -assert.equal(uint8.get(3), 0x0b); +assert.equal(uint8[1], 0x09); +assert.equal(uint8[2], 0x0a); +assert.equal(uint8[3], 0x0b); // test clamped array var uint8c = new Uint8ClampedArray(buffer); @@ -169,8 +169,8 @@ uint8c[1] = 257; assert.equal(uint8c[0], 0); assert.equal(uint8c[1], 255); -uint8c.set(0, -10); -uint8c.set(1, 260); +uint8c[0] = -10; +uint8c[1] = 260; assert.equal(uint8c[0], 0); assert.equal(uint8c[1], 255);