diff --git a/js/src/builtin/AtomicsObject.cpp b/js/src/builtin/AtomicsObject.cpp index bb2f948d8a..a4ae0736d4 100644 --- a/js/src/builtin/AtomicsObject.cpp +++ b/js/src/builtin/AtomicsObject.cpp @@ -83,8 +83,7 @@ static bool ReportOutOfRange(JSContext* cx) { // Use JSMSG_BAD_INDEX here even if it is generic, since that is - // the message used by ToIntegerIndex for its initial range - // checking. + // the message used by NonStandardToIndex for its initial range checking. JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX); return false; } @@ -114,7 +113,7 @@ static bool GetTypedArrayIndex(JSContext* cx, HandleValue v, Handle view, uint32_t* offset) { uint64_t index; - if (!js::ToIntegerIndex(cx, v, &index)) + if (!NonStandardToIndex(cx, v, &index)) return false; if (index >= view->length()) return ReportOutOfRange(cx); diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp index 598cf7caf0..ee8a7137b7 100644 --- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -1725,8 +1725,9 @@ js::ToLengthClamped(JSContext*, HandleValue, uint32_t*, bool*); template bool js::ToLengthClamped(ExclusiveContext*, HandleValue, uint32_t*, bool*); +//Non-standard: Used by Atomics. bool -js::ToIntegerIndex(JSContext* cx, JS::HandleValue v, uint64_t* index) +js::NonStandardToIndex(JSContext* cx, HandleValue v, uint64_t* index) { // Fast common case. if (v.isInt32()) { @@ -1776,7 +1777,7 @@ js::ToIntegerIndex(JSContext* cx, JS::HandleValue v, uint64_t* index) // ES2017 draft 7.1.17 ToIndex bool -js::ToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index) +js::ToIndex(JSContext* cx, JS::HandleValue v, const unsigned errorNumber, uint64_t* index) { // Step 1. if (v.isUndefined()) { @@ -1794,7 +1795,7 @@ js::ToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index) // 2. Step eliminates < 0, +0 == -0 with SameValueZero. // 3/4. Limit to <= 2^53-1, so everything above should fail. if (integerIndex < 0 || integerIndex >= DOUBLE_INTEGRAL_PRECISION_LIMIT) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX); + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, errorNumber); return false; } @@ -1803,6 +1804,12 @@ js::ToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index) return true; } +bool +js::ToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index) +{ + return ToIndex(cx, v, JSMSG_BAD_INDEX, index); +} + template bool js_strtod(ExclusiveContext* cx, const CharT* begin, const CharT* end, const CharT** dEnd, diff --git a/js/src/jsnum.h b/js/src/jsnum.h index 7c96bfb652..a2759aa65f 100644 --- a/js/src/jsnum.h +++ b/js/src/jsnum.h @@ -292,8 +292,7 @@ ToInteger(JSContext* cx, HandleValue v, double* dp) template MOZ_MUST_USE bool ToLengthClamped(T* cx, HandleValue v, uint32_t* out, bool* overflow); -/* Convert and range check an index value as for DataView, SIMD, and Atomics - * operations, eg ES7 24.2.1.1, DataView's GetViewValue(): +/* Convert and range check an index value for Atomics * * 1. numericIndex = ToNumber(argument) (may throw TypeError) * 2. intIndex = ToInteger(numericIndex) @@ -310,7 +309,7 @@ MOZ_MUST_USE bool ToLengthClamped(T* cx, HandleValue v, uint32_t* out, bool* ove * * The returned index will always be in the range 0 <= *index <= 2^53. */ -MOZ_MUST_USE bool ToIntegerIndex(JSContext* cx, JS::HandleValue v, uint64_t* index); +MOZ_MUST_USE bool NonStandardToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index); /* ES2017 draft 7.1.17 ToIndex * @@ -319,6 +318,7 @@ MOZ_MUST_USE bool ToIntegerIndex(JSContext* cx, JS::HandleValue v, uint64_t* ind * * The returned index will always be in the range 0 <= *index <= 2^53-1. */ +MOZ_MUST_USE bool ToIndex(JSContext* cx, JS::HandleValue v, const unsigned errorNumber, uint64_t* index); MOZ_MUST_USE bool ToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index); MOZ_MUST_USE inline bool diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 06e31f208c..7def8c7e1d 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -286,6 +286,7 @@ ArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp) return false; } + // Step 3. RootedObject proto(cx); RootedObject newTarget(cx, &args.newTarget().toObject()); if (!GetPrototypeFromConstructor(cx, newTarget, &proto)) diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index de7ce028eb..232fde02d3 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -675,7 +675,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject makeTypedArrayWithTemplate(JSContext* cx, TypedArrayObject* templateObj, int32_t len) { if (len < 0 || uint32_t(len) >= INT32_MAX / sizeof(NativeType)) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS); + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH); return nullptr; } @@ -745,18 +745,16 @@ class TypedArrayObjectTemplate : public TypedArrayObject MOZ_ASSERT(args.isConstructing()); RootedObject newTarget(cx, &args.newTarget().toObject()); - /* () or (number) */ - uint32_t len = 0; - if (args.length() == 0 || ValueIsLength(args[0], &len)) - return fromLength(cx, len, newTarget); + /* () or (length) */ + if (args.length() == 0 || !args[0].isObject()) { + uint64_t len; + if (!ToIndex(cx, args.get(0), JSMSG_BAD_ARRAY_LENGTH, &len)) + return nullptr; - /* (not an object) */ - if (!args[0].isObject()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS); - return nullptr; + return fromLength(cx, len, newTarget); } - RootedObject dataObj(cx, &args.get(0).toObject()); + RootedObject dataObj(cx, &args[0].toObject()); /* * (typedArray) @@ -933,8 +931,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject MutableHandle buffer) { if (count >= INT32_MAX / unit) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NEED_DIET, - "size and count"); + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH); return false; } uint32_t byteLength = count * unit; @@ -957,17 +954,22 @@ class TypedArrayObjectTemplate : public TypedArrayObject } static JSObject* - fromLength(JSContext* cx, uint32_t nelements, HandleObject newTarget = nullptr) + fromLength(JSContext* cx, uint64_t nelements, HandleObject newTarget = nullptr) { RootedObject proto(cx); if (!GetPrototypeForInstance(cx, newTarget, &proto)) return nullptr; + if (nelements > UINT32_MAX) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH); + return nullptr; + } + Rooted buffer(cx); - if (!maybeCreateArrayBuffer(cx, nelements, BYTES_PER_ELEMENT, nullptr, &buffer)) + if (!maybeCreateArrayBuffer(cx, uint32_t(nelements), BYTES_PER_ELEMENT, nullptr, &buffer)) return nullptr; - return makeInstance(cx, buffer, 0, nelements, proto); + return makeInstance(cx, buffer, 0, uint32_t(nelements), proto); } static bool