Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/Runtime/Library/ArrayBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ namespace Js
uint32 byteLength = 0;
if (args.Info.Count > 1)
{
byteLength = ToIndex(args[1], JSERR_ArrayLengthConstructIncorrect, scriptContext, MaxArrayBufferLength, false);
byteLength = ToIndex(args[1], JSERR_ArrayLengthConstructIncorrect, scriptContext, MaxArrayBufferLength);
}

RecyclableObject* newArr = scriptContext->GetLibrary()->CreateArrayBuffer(byteLength);
Expand Down
49 changes: 17 additions & 32 deletions lib/Runtime/Library/DataView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ namespace Js
uint32 byteLength = 0;
uint32 mappedLength;
int32 offset = 0;
double numberOffset = 0;
ArrayBufferBase* arrayBuffer = nullptr;
DataView* dataView;

Expand All @@ -49,7 +48,7 @@ namespace Js
{
case S_OK:
case S_FALSE:
arrayBuffer = static_cast<ArrayBuffer *> (ab);
arrayBuffer = ab;
// Both of these cases will be handled by the arrayBuffer null check.
break;

Expand All @@ -74,50 +73,37 @@ namespace Js
}
}

//4. Let numberOffset be ToNumber(byteOffset).
//5. Let offset be ToInteger(numberOffset).
//6. ReturnIfAbrupt(offset).
//7. If numberOffset <> offset or offset < 0, throw a RangeError exception.
//4. Let offset be ToIndex(byteOffset).
if (args.Info.Count > 2)
{
Var secondArgument = args[2];
numberOffset = JavascriptConversion::ToNumber(secondArgument, scriptContext);
offset = JavascriptConversion::ToInt32(numberOffset);

if (offset < 0 ||
numberOffset != offset)
{
JavascriptError::ThrowRangeError(
scriptContext, JSERR_DataView_InvalidArgument, _u("byteOffset"));
}
offset = ArrayBuffer::ToIndex(secondArgument, JSERR_ArrayLengthConstructIncorrect, scriptContext, ArrayBuffer::MaxArrayBufferLength, false);
}

//8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
//5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
if (arrayBuffer->IsDetached())
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedDataView);
}

//9. Let bufferByteLength be the value of buffer's[[ArrayBufferByteLength]] internal slot.
//10. If offset > bufferByteLength, throw a RangeError exception.

//6. Let bufferByteLength be the value of buffer's[[ArrayBufferByteLength]] internal slot.
//7. If offset > bufferByteLength, throw a RangeError exception.
byteLength = arrayBuffer->GetByteLength();
if ((uint32)offset > byteLength)
{
JavascriptError::ThrowRangeError(
scriptContext, JSERR_DataView_InvalidArgument, _u("byteOffset"));
}

//11. If byteLength is undefined, then
//8. If byteLength is either not present or is undefined, then
// a. Let viewByteLength be bufferByteLength - offset.
//12. Else,
// a. Let viewByteLength be ToLength(byteLength).
// b. ReturnIfAbrupt(viewLength).
// c. If offset + viewByteLength > bufferByteLength, throw a RangeError exception.
//9. Else,
// a. Let viewByteLength be ToIndex(byteLength).
// b. If offset + viewByteLength > bufferByteLength, throw a RangeError exception.
if (args.Info.Count > 3 && !JavascriptOperators::IsUndefinedObject(args[3]))
{
Var thirdArgument = args[3];
mappedLength = (uint32)JavascriptConversion::ToLength(thirdArgument, scriptContext);
mappedLength = ArrayBuffer::ToIndex(thirdArgument, JSERR_ArrayLengthConstructIncorrect, scriptContext, ArrayBuffer::MaxArrayBufferLength, false);
uint32 viewRange = mappedLength + offset;

if (viewRange > byteLength || viewRange < mappedLength) // overflow indicates out-of-range
Expand All @@ -131,13 +117,12 @@ namespace Js
mappedLength = byteLength - offset;
}

//13. Let O be OrdinaryCreateFromConstructor(NewTarget, "%DataViewPrototype%", [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]]).
//14. ReturnIfAbrupt(O).
//15. Set O's[[DataView]] internal slot to true.
//16. Set O's[[ViewedArrayBuffer]] internal slot to buffer.
//17. Set O's[[ByteLength]] internal slot to viewByteLength.
//18. Set O's[[ByteOffset]] internal slot to offset.
//19. Return O.
//10. Let O be OrdinaryCreateFromConstructor(NewTarget, "%DataViewPrototype%", [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]]).
//11. Set O's[[DataView]] internal slot to true.
//12. Set O's[[ViewedArrayBuffer]] internal slot to buffer.
//13. Set O's[[ByteLength]] internal slot to viewByteLength.
//14. Set O's[[ByteOffset]] internal slot to offset.
//15. Return O.
dataView = scriptContext->GetLibrary()->CreateDataView(arrayBuffer, offset, mappedLength);
return isCtorSuperCall ?
JavascriptOperators::OrdinaryCreateFromConstructor(RecyclableObject::FromVar(newTarget), dataView, nullptr, scriptContext) :
Expand Down
6 changes: 5 additions & 1 deletion lib/Runtime/Library/TypedArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ namespace Js
Var TypedArrayBase::CreateNewInstance(Arguments& args, ScriptContext* scriptContext, uint32 elementSize, PFNCreateTypedArray pfnCreateTypedArray)
{
uint32 byteLength = 0;
uint32 newByteLength = 0;
int32 offset = 0;
int32 mappedLength = -1;
uint32 elementCount = 0;
Expand Down Expand Up @@ -509,12 +510,15 @@ namespace Js
if (args.Info.Count > 3 && !JavascriptOperators::IsUndefinedObject(args[3]))
{
mappedLength = ArrayBuffer::ToIndex(args[3], JSERR_InvalidTypedArrayLength, scriptContext, ArrayBuffer::MaxArrayBufferLength / elementSize, false);
newByteLength = mappedLength * elementSize;

if ((uint32)mappedLength > (byteLength - offset)/ elementSize)
if (offset + newByteLength > byteLength)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which case was this fixing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed a slight change in the spec while reviewing the indexing related changes. Please refer to the spec at https://tc39.github.io/ecma262/#sec-typedarray-buffer-byteoffset-length section 22.2.4.5 step 12.

{
JavascriptError::ThrowRangeError(
scriptContext, JSERR_InvalidTypedArrayLength);
}

byteLength = newByteLength;
}
else
{
Expand Down
54 changes: 54 additions & 0 deletions test/typedarray/TypedArrayBuiltins.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,60 @@ var tests = [
test(taCtor);
}
}
},
{
name: "TypedArray : Error cases for constructor TypedArray( buffer, byteOffset, length )",
body: function () {
var sourceArrayBuffer1 = new ArrayBuffer(10);

// offset > byteLength
function TestOffsetBeyondSourceArrayBufferLength()
{
new Int16Array(sourceArrayBuffer1, 12);
}

assert.throws(
TestOffsetBeyondSourceArrayBufferLength,
RangeError,
"TypedArray: Expected the function to throw RangeError as (offset > byteLength).",
"Invalid offset/length when creating typed array")

// offset % elementSize != 0
function TestIncorrectOffset()
{
new Int16Array(sourceArrayBuffer1, 7, 1);
}

assert.throws(
TestIncorrectOffset,
RangeError,
"TypedArray: Expected the function to throw RangeError as (offset % elementSize) != 0.",
"Invalid offset/length when creating typed array")

// (Length * elementSize + offset) beyond array buffer length.
function TestLengthBeyondSourceArrayBufferLength()
{
new Int16Array(sourceArrayBuffer1, 6, 4);
}

assert.throws(
TestLengthBeyondSourceArrayBufferLength,
RangeError,
"TypedArray: Expected the function to throw RangeError as ((Length * elementSize + offset)) != byteLength.",
"Invalid offset/length when creating typed array")

// (byteLength - offset) % elementSize != 0
function TestOffsetPlusElementSizeBeyondSourceArrayBufferLength()
{
new Int32Array(sourceArrayBuffer1, 4);
}

assert.throws(
TestOffsetPlusElementSizeBeyondSourceArrayBufferLength,
RangeError,
"TypedArray: Expected the function to throw RangeError as (byteLength - offset) % elementSize != 0.",
"Invalid offset/length when creating typed array")
}
}
];

Expand Down
Loading