Issue #1240 - Part 6b - Use ToIndex when constructing TypedArray with length argument. https://bugzilla.mozilla.org/show_bug.cgi?id=1317383 Part 2.

This commit is contained in:
Brian Smith 2023-07-19 16:36:58 -05:00 • committed by roytam1
commit e004b99054
5 changed files with 51 additions and 43 deletions

View file

@ -1768,6 +1768,35 @@ js::ToIntegerIndex(JSContext* cx, JS::HandleValue v, uint64_t* index)
return true; return true;
} }
// ES2017 draft 7.1.17 ToIndex
bool
js::ToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index)
{
// Step 1.
if (v.isUndefined()) {
*index = 0;
return true;
}
// Step 2.a.
double integerIndex;
if (!ToInteger(cx, v, &integerIndex))
return false;
// Inlined version of ToLength.
// 1. Already an integer.
// 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);
return false;
}
// Step 3.
*index = uint64_t(integerIndex);
return true;
}
template <typename CharT> template <typename CharT>
bool bool
js_strtod(ExclusiveContext* cx, const CharT* begin, const CharT* end, const CharT** dEnd, js_strtod(ExclusiveContext* cx, const CharT* begin, const CharT* end, const CharT** dEnd,

View file

@ -308,6 +308,15 @@ MOZ_MUST_USE bool ToLengthClamped(T* cx, HandleValue v, uint32_t* out, bool* ove
*/ */
MOZ_MUST_USE bool ToIntegerIndex(JSContext* cx, JS::HandleValue v, uint64_t* index); MOZ_MUST_USE bool ToIntegerIndex(JSContext* cx, JS::HandleValue v, uint64_t* index);
/* ES2017 draft 7.1.17 ToIndex
*
* Return true and set |*index| to the integer value if |v| is a valid
* integer index value. Otherwise report a RangeError and return false.
*
* The returned index will always be in the range 0 <= *index <= 2^53-1.
*/
MOZ_MUST_USE bool ToIndex(JSContext* cx, JS::HandleValue v, uint64_t* index);
MOZ_MUST_USE inline bool MOZ_MUST_USE inline bool
SafeAdd(int32_t one, int32_t two, int32_t* res) SafeAdd(int32_t one, int32_t two, int32_t* res)
{ {

View file

@ -264,27 +264,24 @@ ArrayBufferObject::fun_isView(JSContext* cx, unsigned argc, Value* vp)
return true; return true;
} }
/*
* new ArrayBuffer(byteLength) // ES2017 draft 24.1.2.1
*/
bool bool
ArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp) ArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
{ {
CallArgs args = CallArgsFromVp(argc, vp); CallArgs args = CallArgsFromVp(argc, vp);
// Step 1.
if (!ThrowIfNotConstructing(cx, args, "ArrayBuffer")) if (!ThrowIfNotConstructing(cx, args, "ArrayBuffer"))
return false; return false;
int32_t nbytes = 0; // Step 2.
if (argc > 0 && !ToInt32(cx, args[0], &nbytes)) uint64_t byteLength;
if (!ToIndex(cx, args.get(0), &byteLength))
return false; return false;
if (nbytes < 0) { // Non-standard: Refuse to allocate buffers larger than ~2 GiB.
/* if (byteLength > INT32_MAX) {
* We're just not going to support arrays that are bigger than what will fit
* as an integer value; if someone actually ever complains (validly), then we
* can fix.
*/
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH); JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
return false; return false;
} }
@ -294,7 +291,7 @@ ArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
if (!GetPrototypeFromConstructor(cx, newTarget, &proto)) if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
return false; return false;
JSObject* bufobj = create(cx, uint32_t(nbytes), proto); JSObject* bufobj = create(cx, uint32_t(byteLength), proto);
if (!bufobj) if (!bufobj)
return false; return false;
args.rval().setObject(*bufobj); args.rval().setObject(*bufobj);

View file

@ -1898,10 +1898,8 @@ DataViewObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
template <typename NativeType> template <typename NativeType>
/* static */ uint8_t* /* static */ uint8_t*
DataViewObject::getDataPointer(JSContext* cx, Handle<DataViewObject*> obj, double offset) DataViewObject::getDataPointer(JSContext* cx, Handle<DataViewObject*> obj, uint64_t offset)
{ {
MOZ_ASSERT(offset >= 0);
const size_t TypeSize = sizeof(NativeType); const size_t TypeSize = sizeof(NativeType);
if (offset > UINT32_MAX - TypeSize || offset + TypeSize > obj->byteLength()) { if (offset > UINT32_MAX - TypeSize || offset + TypeSize > obj->byteLength()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE, JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE,
@ -1989,31 +1987,6 @@ struct DataViewIO
} }
}; };
static bool
ToIndex(JSContext* cx, HandleValue v, double* index)
{
if (v.isUndefined()) {
*index = 0.0;
return true;
}
double integerIndex;
if (!ToInteger(cx, v, &integerIndex))
return false;
// Inlined version of ToLength.
// 1. Already an integer
// 2. Step eliminates < 0, +0 == -0 with SameValueZero
// 3/4. Limit to <= 2^53-1, so everything above should fail.
if (integerIndex < 0 || integerIndex > 9007199254740991) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
return false;
}
*index = integerIndex;
return true;
}
template<typename NativeType> template<typename NativeType>
/* static */ bool /* static */ bool
DataViewObject::read(JSContext* cx, Handle<DataViewObject*> obj, DataViewObject::read(JSContext* cx, Handle<DataViewObject*> obj,
@ -2023,7 +1996,7 @@ DataViewObject::read(JSContext* cx, Handle<DataViewObject*> obj,
// Step 3. unnecessary assert // Step 3. unnecessary assert
// Step 4. // Step 4.
double getIndex; uint64_t getIndex;
if (!ToIndex(cx, args.get(0), &getIndex)) if (!ToIndex(cx, args.get(0), &getIndex))
return false; return false;
@ -2111,7 +2084,7 @@ DataViewObject::write(JSContext* cx, Handle<DataViewObject*> obj,
// Step 3. unnecessary assert // Step 3. unnecessary assert
// Step 4. // Step 4.
double getIndex; uint64_t getIndex;
if (!ToIndex(cx, args.get(0), &getIndex)) if (!ToIndex(cx, args.get(0), &getIndex))
return false; return false;

View file

@ -442,7 +442,7 @@ class DataViewObject : public NativeObject
template <typename NativeType> template <typename NativeType>
static uint8_t* static uint8_t*
getDataPointer(JSContext* cx, Handle<DataViewObject*> obj, double offset); getDataPointer(JSContext* cx, Handle<DataViewObject*> obj, uint64_t offset);
template<Value ValueGetter(DataViewObject* view)> template<Value ValueGetter(DataViewObject* view)>
static bool static bool