Bug 1520434-Improve the error messages when creating unaligned typed arrays r=mgaudet

Improved error messages emitted by JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS.Error messages improved to specify the type and cause of error.
Added the test to check the error messages modified matches the expected cases.

Differential Revision: https://phabricator.services.mozilla.com/D113874
This commit is contained in:
AshwiniWankhede 2021-05-04 15:34:36 +00:00
parent 0882de8cee
commit b332049130
4 changed files with 96 additions and 10 deletions

View File

@ -159,6 +159,32 @@ static inline const char* name(Type atype) {
MOZ_CRASH("invalid scalar type");
}
static inline const char* byteSizeString(Type atype) {
switch (atype) {
case Int8:
case Uint8:
case Uint8Clamped:
return "1";
case Int16:
case Uint16:
return "2";
case Int32:
case Uint32:
case Float32:
return "4";
case Int64:
case Float64:
case BigInt64:
case BigUint64:
return "8";
case Simd128:
return "16";
case MaxTypedArrayViewType:
break;
}
MOZ_CRASH("invalid scalar type");
}
} // namespace Scalar
} // namespace js

View File

@ -640,7 +640,12 @@ MSG_DEF(JSMSG_SHORT_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected ArrayBuff
MSG_DEF(JSMSG_TYPED_ARRAY_BAD_ARGS, 0, JSEXN_TYPEERR, "invalid arguments")
MSG_DEF(JSMSG_TYPED_ARRAY_NEGATIVE_ARG,1, JSEXN_RANGEERR, "argument {0} must be >= 0")
MSG_DEF(JSMSG_TYPED_ARRAY_DETACHED, 0, JSEXN_TYPEERR, "attempting to access detached ArrayBuffer")
MSG_DEF(JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS, 0, JSEXN_RANGEERR, "attempting to construct out-of-bounds TypedArray on ArrayBuffer")
MSG_DEF(JSMSG_TYPED_ARRAY_CONSTRUCT_OFFSET_BOUNDS, 2, JSEXN_RANGEERR, "start offset of {0}Array should be a multiple of {1}")
MSG_DEF(JSMSG_TYPED_ARRAY_CONSTRUCT_OFFSET_MISALIGNED, 2, JSEXN_RANGEERR, "buffer length for {0}Array should be a multiple of {1}")
MSG_DEF(JSMSG_TYPED_ARRAY_CONSTRUCT_OFFSET_LENGTH_BOUNDS, 1, JSEXN_RANGEERR, "size of buffer is too small for {0}Array with byteOffset")
MSG_DEF(JSMSG_TYPED_ARRAY_CONSTRUCT_ARRAY_LENGTH_BOUNDS, 1, JSEXN_RANGEERR, "attempting to construct out-of-bounds {0}Array on ArrayBuffer")
MSG_DEF(JSMSG_TYPED_ARRAY_CONSTRUCT_TOO_LARGE, 1, JSEXN_RANGEERR, "{0}Array too large")
MSG_DEF(JSMSG_TYPED_ARRAY_CALL_OR_CONSTRUCT, 1, JSEXN_TYPEERR, "cannot directly {0} builtin %TypedArray%")
MSG_DEF(JSMSG_NON_TYPED_ARRAY_RETURNED, 0, JSEXN_TYPEERR, "constructor didn't return TypedArray object")
MSG_DEF(JSMSG_SHORT_TYPED_ARRAY_RETURNED, 2, JSEXN_TYPEERR, "expected TypedArray of at least length {0}, but constructor returned TypedArray of length {1}")

View File

@ -0,0 +1,38 @@
function assertThrowsMessage(f, regexp) {
var threw = true;
var error = null;
try {
f();
threw = false;
} catch (e) {
error = e;
}
// Make sure f threw
assertEq(threw, true);
// Make sure the message is as we expected
assertEq(regexp.test(error.message), true);
}
var shared = new SharedArrayBuffer(4096);
assertThrowsMessage(() => new Int32Array(shared, 7), /start offset of Int32Array should be a multiple of 4/);
var shared = new SharedArrayBuffer(4096);
assertThrowsMessage(() => new Float64Array(shared, 3), /start offset of Float64Array should be a multiple of 8/);
var shared = new SharedArrayBuffer(1025);
assertThrowsMessage(() => new Float32Array(shared, 8), /buffer length for Float32Array should be a multiple of 4/);
var shared = new SharedArrayBuffer(513);
assertThrowsMessage(() => new Int16Array(shared, 8), /buffer length for Int16Array should be a multiple of 2/);
var shared = new SharedArrayBuffer(32);
assertThrowsMessage(() => new Int16Array(shared, 36), /size of buffer is too small for Int16Array with byteOffset/);
var shared = new SharedArrayBuffer(2048);
assertThrowsMessage(() => new BigInt64Array(shared, 4096), /size of buffer is too small for BigInt64Array with byteOffset/);
var shared = new SharedArrayBuffer(4096);
assertThrowsMessage(() => new Int32Array(shared, 4096, 4), /attempting to construct out-of-bounds Int32Array on ArrayBuffer/);
var shared = new SharedArrayBuffer(1024);
assertThrowsMessage(() => new Float32Array(shared, 800, 300), /attempting to construct out-of-bounds Float32Array on ArrayBuffer/);

View File

@ -641,7 +641,9 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
// Step 7.
if (*byteOffset % BYTES_PER_ELEMENT != 0) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
JSMSG_TYPED_ARRAY_CONSTRUCT_OFFSET_BOUNDS,
Scalar::name(ArrayTypeID()),
Scalar::byteSizeString(ArrayTypeID()));
return false;
}
}
@ -681,12 +683,22 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
size_t len;
if (lengthIndex == UINT64_MAX) {
// Steps 11.a, 11.c.
if (bufferByteLength % BYTES_PER_ELEMENT != 0 ||
byteOffset > bufferByteLength) {
if (bufferByteLength % BYTES_PER_ELEMENT != 0) {
// The given byte array doesn't map exactly to
// |BYTES_PER_ELEMENT * N| or |byteOffset| is invalid.
// |BYTES_PER_ELEMENT * N|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
JSMSG_TYPED_ARRAY_CONSTRUCT_OFFSET_MISALIGNED,
Scalar::name(ArrayTypeID()),
Scalar::byteSizeString(ArrayTypeID()));
return false;
}
if (byteOffset > bufferByteLength) {
// |byteOffset| is invalid.
JS_ReportErrorNumberASCII(
cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_CONSTRUCT_OFFSET_LENGTH_BOUNDS,
Scalar::name(ArrayTypeID()));
return false;
}
@ -700,8 +712,10 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
// Step 12.b.
if (byteOffset + newByteLength > bufferByteLength) {
// |byteOffset + newByteLength| is too big for the arraybuffer
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
JS_ReportErrorNumberASCII(
cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_CONSTRUCT_ARRAY_LENGTH_BOUNDS,
Scalar::name(ArrayTypeID()));
return false;
}
@ -710,7 +724,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
if (len > maxByteLength() / BYTES_PER_ELEMENT) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
JSMSG_TYPED_ARRAY_CONSTRUCT_TOO_LARGE,
Scalar::name(ArrayTypeID()));
return false;
}
@ -811,7 +826,9 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
size_t byteOffset, int64_t lengthInt) {
if (byteOffset % BYTES_PER_ELEMENT != 0) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_TYPED_ARRAY_CONSTRUCT_BOUNDS);
JSMSG_TYPED_ARRAY_CONSTRUCT_OFFSET_BOUNDS,
Scalar::name(ArrayTypeID()),
Scalar::byteSizeString(ArrayTypeID()));
return nullptr; // invalid byteOffset
}