diff --git a/src/v8_typed_array.cc b/src/v8_typed_array.cc index c388cb9cf1..fe4b4f0abb 100644 --- a/src/v8_typed_array.cc +++ b/src/v8_typed_array.cc @@ -122,7 +122,7 @@ class ArrayBuffer { } }; -static bool checkAlignment(unsigned int val, unsigned int bytes) { +static bool checkAlignment(size_t val, unsigned int bytes) { return (val & (bytes - 1)) == 0; // Handles bytes == 0. } @@ -186,16 +186,13 @@ class TypedArray { if (node::Buffer::HasInstance(args[0]) || ArrayBuffer::HasInstance(args[0])) { // ArrayBuffer constructor. buffer = v8::Local::Cast(args[0]); - unsigned int buflen = + size_t buflen = buffer->GetIndexedPropertiesExternalArrayDataLength(); if (!args[1]->IsUndefined() && args[1]->Int32Value() < 0) return ThrowRangeError("Byte offset out of range."); byte_offset = args[1]->IsUndefined() ? 0 : args[1]->Uint32Value(); - if (!checkAlignment(byte_offset, TBytes)) - return ThrowRangeError("Byte offset is not aligned."); - if (args.Length() > 2) { if (args[2]->Int32Value() < 0) return ThrowRangeError("Length out of range."); @@ -214,10 +211,14 @@ class TypedArray { return ThrowRangeError("Length is out of range."); } - // TODO(deanm): Error check. void* buf = buffer->GetIndexedPropertiesExternalArrayData(); + char* begin = reinterpret_cast(buf) + byte_offset; + + if (!checkAlignment(reinterpret_cast(begin), TBytes)) + return ThrowRangeError("Byte offset is not aligned."); + args.This()->SetIndexedPropertiesToExternalArrayData( - reinterpret_cast(buf) + byte_offset, TEAType, length); + begin, TEAType, length); } else if (args[0]->IsObject()) { // TypedArray / type[] constructor. v8::Local obj = v8::Local::Cast(args[0]); diff --git a/test/simple/test-typed-arrays.js b/test/simple/test-typed-arrays.js index f8e5cbdb00..803f18a729 100644 --- a/test/simple/test-typed-arrays.js +++ b/test/simple/test-typed-arrays.js @@ -53,13 +53,28 @@ var assert = require('assert'); }); // initialize a zero-filled buffer -var buffer = new Buffer(8); +var buffer = new Buffer(16); buffer.fill(0); -var uint8 = new Uint8Array(buffer); -var uint16 = new Uint16Array(buffer); -var uint16slice = new Uint16Array(buffer, 2, 2); -var uint32 = new Uint32Array(buffer); +// only one of these instantiations should succeed, as the other ones will be +// unaligned +var errors = 0; +var offset; +for (var i = 0; i < 8; i++) { + try { + new Float64Array(buffer, i); + offset = i; + } catch (e) { + errors += 1; + } +} + +assert.equal(errors, 7); + +var uint8 = new Uint8Array(buffer, offset); +var uint16 = new Uint16Array(buffer, offset); +var uint16slice = new Uint16Array(buffer, offset + 2, 2); +var uint32 = new Uint32Array(buffer, offset); assert.equal(uint8.BYTES_PER_ELEMENT, 1); assert.equal(uint16.BYTES_PER_ELEMENT, 2); @@ -67,20 +82,19 @@ assert.equal(uint16slice.BYTES_PER_ELEMENT, 2); assert.equal(uint32.BYTES_PER_ELEMENT, 4); // now change the underlying buffer -buffer[0] = 0x08; -buffer[1] = 0x09; -buffer[2] = 0x0a; -buffer[3] = 0x0b; -buffer[4] = 0x0c; -buffer[5] = 0x0d; -buffer[6] = 0x0e; -buffer[7] = 0x0f; +buffer[offset ] = 0x08; +buffer[offset + 1] = 0x09; +buffer[offset + 2] = 0x0a; +buffer[offset + 3] = 0x0b; +buffer[offset + 4] = 0x0c; +buffer[offset + 5] = 0x0d; +buffer[offset + 6] = 0x0e; +buffer[offset + 7] = 0x0f; /* This is what we expect the variables to look like at this point (on little-endian machines): - buffer | 0x08 | 0x09 | 0x0a | 0x0b | 0x0c | 0x0d | 0x0e | 0x0f | uint8 | 0x08 | 0x09 | 0x0a | 0x0b | 0x0c | 0x0d | 0x0e | 0x0f | uint16 | 0x0908 | 0x0b0a | 0x0d0c | 0x0f0e | uint16slice --------------| 0x0b0a | 0x0d0c |--------------