Bug 1891118 - Move arraybuffer diagnostic assertions into spidermonkey r=peterv,jandem

Differential Revision: https://phabricator.services.mozilla.com/D207310
This commit is contained in:
Steve Fink 2024-05-13 18:33:37 +00:00
parent 48ec93874d
commit d8e98a7383
3 changed files with 33 additions and 74 deletions

View File

@ -13,6 +13,7 @@
#include "js/ArrayBuffer.h"
#include "js/ArrayBufferMaybeShared.h"
#include "js/Context.h"
#include "js/experimental/TypedData.h" // js::Unwrap(Ui|I)nt(8|16|32)Array, js::Get(Ui|I)nt(8|16|32)ArrayLengthAndData, js::UnwrapUint8ClampedArray, js::GetUint8ClampedArrayLengthAndData, js::UnwrapFloat(32|64)Array, js::GetFloat(32|64)ArrayLengthAndData, JS_GetArrayBufferViewType
#include "js/GCAPI.h" // JS::AutoCheckCannotGC
#include "js/RootingAPI.h" // JS::Rooted
@ -671,80 +672,9 @@ struct TypedArray_base : public SpiderMonkeyInterfaceObjectStorage,
MOZ_CRASH("Null js::CheckedUnwrapStatic(mImplObj)");
}
}
if (!JS::IsArrayBufferViewShared(view)) {
JSAutoRealm ar(jsapi.cx(), view);
bool unused;
bool noBuffer;
{
JSObject* buffer =
JS_GetArrayBufferViewBuffer(jsapi.cx(), view, &unused);
noBuffer = !buffer;
}
if (noBuffer) {
if (JS_IsTypedArrayObject(view)) {
JS::Value bufferSlot =
JS::GetReservedSlot(view, /* BUFFER_SLOT */ 0);
if (bufferSlot.isNull()) {
MOZ_CRASH("TypedArrayObject with bufferSlot containing null");
} else if (bufferSlot.isBoolean()) {
// If we're here then TypedArrayObject::ensureHasBuffer must have
// failed in the call to JS_GetArrayBufferViewBuffer.
if (JS_IsThrowingOutOfMemory(jsapi.cx())) {
size_t length = JS_GetTypedArrayByteLength(view);
if (!JS::GetReservedSlot(view, /* DATA_SLOT */ 3)
.isUndefined() &&
length <= JS_MaxMovableTypedArraySize()) {
MOZ_CRASH(
"We did run out of memory, maybe trying to uninline the "
"buffer");
}
if (length < INT32_MAX) {
MOZ_CRASH(
"We did run out of memory trying to create a buffer "
"smaller than 2GB - 1");
} else if (length < UINT32_MAX) {
MOZ_CRASH(
"We did run out of memory trying to create a between 2GB "
"and 4GB - 1");
} else {
MOZ_CRASH(
"We did run out of memory trying to create a buffer "
"bigger than 4GB - 1");
}
} else if (JS_IsExceptionPending(jsapi.cx())) {
JS::Rooted<JS::Value> exn(jsapi.cx());
if (JS_GetPendingException(jsapi.cx(), &exn) &&
exn.isObject()) {
JS::Rooted<JSObject*> exnObj(jsapi.cx(), &exn.toObject());
JSErrorReport* err =
JS_ErrorFromException(jsapi.cx(), exnObj);
if (err && err->errorNumber == JSMSG_BAD_ARRAY_LENGTH) {
MOZ_CRASH("Length was too big");
}
}
}
// Did ArrayBufferObject::createBufferAndData fail without OOM?
MOZ_CRASH("TypedArrayObject with bufferSlot containing boolean");
} else if (bufferSlot.isObject()) {
if (!bufferSlot.toObjectOrNull()) {
MOZ_CRASH(
"TypedArrayObject with bufferSlot containing null object");
} else {
MOZ_CRASH(
"JS_GetArrayBufferViewBuffer failed but bufferSlot "
"contains a non-null object");
}
} else {
MOZ_CRASH(
"TypedArrayObject with bufferSlot containing weird value");
}
} else {
MOZ_CRASH("JS_GetArrayBufferViewBuffer failed for DataViewObject");
}
}
}
}
#endif
JS::AutoBrittleMode abm(jsapi.cx());
if (!JS::EnsureNonInlineArrayBufferOrView(jsapi.cx(), mImplObj)) {
MOZ_CRASH("small oom when moving inline data out-of-line");
}

View File

@ -843,6 +843,8 @@ static ArrayBufferContents AllocateUninitializedArrayBufferContents(
p = static_cast<uint8_t*>(cx->runtime()->onOutOfMemoryCanGC(
js::AllocFunction::Malloc, js::ArrayBufferContentsArena, nbytes));
if (!p) {
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode,
"OOM in AllocateUninitializedArrayBufferContents");
ReportOutOfMemory(cx);
}
}
@ -1753,6 +1755,7 @@ static ArrayBufferType* NewArrayBufferObject(JSContext* cx, HandleObject proto_,
if (!proto) {
proto = GlobalObject::getOrCreatePrototype(cx, JSProto_ArrayBuffer);
if (!proto) {
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "creating ArrayBuffer proto");
return nullptr;
}
}
@ -1770,6 +1773,7 @@ static ArrayBufferType* NewArrayBufferObject(JSContext* cx, HandleObject proto_,
SharedShape::getInitialShape(cx, clasp, cx->realm(), AsTaggedProto(proto),
nfixed, ObjectFlags()));
if (!shape) {
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "get ArrayBuffer initial shape");
return nullptr;
}
@ -1778,7 +1782,12 @@ static ArrayBufferType* NewArrayBufferObject(JSContext* cx, HandleObject proto_,
MOZ_ASSERT(!CanNurseryAllocateFinalizedClass(clasp));
constexpr gc::Heap heap = gc::Heap::Tenured;
return NativeObject::create<ArrayBufferType>(cx, allocKind, heap, shape);
auto* buffer =
NativeObject::create<ArrayBufferType>(cx, allocKind, heap, shape);
if (!buffer) {
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "create NativeObject failed");
}
return buffer;
}
// Creates a new ArrayBufferObject with %ArrayBuffer.prototype% as proto and no
@ -1889,6 +1898,15 @@ ArrayBufferObject::createUninitializedBufferAndData(
? AllocateUninitializedArrayBufferContents(cx, nbytes)
: AllocateArrayBufferContents(cx, nbytes);
if (!data) {
if (cx->brittleMode) {
if (nbytes < INT32_MAX) {
MOZ_DIAGNOSTIC_ASSERT(false, "ArrayBuffer allocation OOM < 2GB - 1");
} else {
MOZ_DIAGNOSTIC_ASSERT(
false,
"ArrayBuffer allocation OOM between 2GB and ByteLengthLimit");
}
}
return {nullptr, nullptr};
}
}
@ -2247,6 +2265,7 @@ ArrayBufferObject* ArrayBufferObject::createZeroed(
JSContext* cx, size_t nbytes, HandleObject proto /* = nullptr */) {
// 24.1.1.1, step 3 (Inlined 6.2.6.1 CreateByteDataBlock, step 2).
if (!CheckArrayBufferTooLarge(cx, nbytes)) {
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "buffer too large");
return nullptr;
}
@ -2469,6 +2488,7 @@ bool ArrayBufferObject::ensureNonInline(JSContext* cx,
if (buffer->isLengthPinned()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_ARRAYBUFFER_LENGTH_PINNED);
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "ArrayBuffer length pinned");
return false;
}

View File

@ -113,7 +113,11 @@ ArrayBufferObjectMaybeShared* ArrayBufferViewObject::ensureBufferObject(
return nullptr;
}
}
return thisObject->bufferEither();
auto* buffer = thisObject->bufferEither();
if (!buffer) {
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "ABV has no buffer");
}
return buffer;
}
bool ArrayBufferViewObject::init(JSContext* cx,
@ -451,6 +455,7 @@ JS_PUBLIC_API JSObject* JS_GetArrayBufferViewBuffer(JSContext* cx,
Rooted<ArrayBufferViewObject*> unwrappedView(
cx, obj->maybeUnwrapAs<ArrayBufferViewObject>());
if (!unwrappedView) {
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "access to buffer denied");
ReportAccessDenied(cx);
return nullptr;
}
@ -468,6 +473,7 @@ JS_PUBLIC_API JSObject* JS_GetArrayBufferViewBuffer(JSContext* cx,
RootedObject buffer(cx, unwrappedBuffer);
if (!cx->compartment()->wrap(cx, &buffer)) {
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "wrapping buffer failed");
return nullptr;
}
@ -586,6 +592,8 @@ JS_PUBLIC_API bool JS::PinArrayBufferOrViewLength(JSObject* obj, bool pin) {
return view->pinLength(pin);
}
MOZ_DIAGNOSTIC_ASSERT(!js::TlsContext.get()->brittleMode,
"invalid type in PinABOVLength");
return false;
}
@ -612,6 +620,7 @@ JS_PUBLIC_API bool JS::EnsureNonInlineArrayBufferOrView(JSContext* cx,
return ArrayBufferViewObject::ensureNonInline(cx, rootedView);
}
MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "unhandled type");
JS_ReportErrorASCII(cx, "unhandled type");
return false;
}