Bug 931218 - Fix an exact rooting hazard in JS_StealArrayBufferContents; r=sfink

This commit is contained in:
Terrence Cole 2013-10-25 11:57:26 -07:00
Родитель 6070d164e6
Коммит 1a61e338d5
4 изменённых файлов: 16 добавлений и 15 удалений

Просмотреть файл

@ -3078,8 +3078,7 @@ JS_NewArrayBufferWithContents(JSContext *cx, void *contents);
* be used until |*contents| is freed or has its ownership transferred.
*/
extern JS_PUBLIC_API(bool)
JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data);
JS_StealArrayBufferContents(JSContext *cx, JS::HandleObject obj, void **contents, uint8_t **data);
/*
* Allocate memory that may be eventually passed to

Просмотреть файл

@ -991,9 +991,10 @@ JSStructuredCloneWriter::transferOwnership()
!tr.empty();
tr.popFront())
{
RootedObject obj(context(), tr.front());
void *content;
uint8_t *data;
if (!JS_StealArrayBufferContents(context(), tr.front(), &content, &data))
if (!JS_StealArrayBufferContents(context(), obj, &content, &data))
return false; // Destructor will clean up the already-transferred data
MOZ_ASSERT(uint32_t(LittleEndian::readUint64(point) >> 32) == SCTAG_TRANSFER_MAP_ENTRY);

Просмотреть файл

@ -670,29 +670,29 @@ ArrayBufferObject::createDataViewForThis(JSContext *cx, unsigned argc, Value *vp
}
bool
ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents, uint8_t **data)
ArrayBufferObject::stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer, void **contents,
uint8_t **data)
{
ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
// Make the data stealable
bool own;
ObjectElements *header = reinterpret_cast<ObjectElements*>(buffer.getTransferableContents(cx, &own));
ObjectElements *header = reinterpret_cast<ObjectElements*>(buffer->getTransferableContents(cx, &own));
if (!header)
return false;
JS_ASSERT(!IsInsideNursery(cx->runtime(), header));
*contents = header;
*data = reinterpret_cast<uint8_t *>(header + 1);
// Neuter the views, which may also mprotect(PROT_NONE) the buffer. So do
// it after copying out the data.
if (!buffer.neuterViews(cx))
if (!buffer->neuterViews(cx))
return false;
if (!own) {
// If header has dynamically allocated elements, revert it back to
// fixed-element storage before neutering it.
buffer.changeContents(cx, ObjectElements::fromElements(buffer.fixedElements()));
buffer->changeContents(cx, ObjectElements::fromElements(buffer->fixedElements()));
}
buffer.neuter(cx);
buffer->neuter(cx);
return true;
}
@ -4088,10 +4088,10 @@ JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents
}
JS_PUBLIC_API(bool)
JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
uint8_t **data)
JS_StealArrayBufferContents(JSContext *cx, HandleObject objArg, void **contents, uint8_t **data)
{
if (!(obj = CheckedUnwrap(obj)))
JSObject *obj = CheckedUnwrap(objArg);
if (!obj)
return false;
if (!obj->is<ArrayBufferObject>()) {
@ -4099,7 +4099,8 @@ JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
return false;
}
if (!ArrayBufferObject::stealContents(cx, obj, contents, data))
Rooted<ArrayBufferObject*> buffer(cx, &obj->as<ArrayBufferObject>());
if (!ArrayBufferObject::stealContents(cx, buffer, contents, data))
return false;
return true;

Просмотреть файл

@ -143,7 +143,7 @@ class ArrayBufferObject : public JSObject
static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
static void restoreArrayBufferLists(ArrayBufferVector &vector);
static bool stealContents(JSContext *cx, JSObject *obj, void **contents,
static bool stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer, void **contents,
uint8_t **data);
static void updateElementsHeader(js::ObjectElements *header, uint32_t bytes) {