Bug 1495573 - avoid double refcount decrement along failure path. r=luke

--HG--
extra : rebase_source : 0894f81f9828fd41a35dbd8c9ccbdfbea4ba58b2
extra : histedit_source : 383355a2244dfba407b54c0e2e1627f9b2a44784
This commit is contained in:
Lars T Hansen 2018-10-02 14:12:41 +02:00
parent d3446d7ede
commit f3b4178593

View File

@ -6686,34 +6686,44 @@ GetSharedObject(JSContext* cx, unsigned argc, Value* vp)
// Flag was set in the sender; ensure it is set in the receiver. // Flag was set in the sender; ensure it is set in the receiver.
MOZ_ASSERT(cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled()); MOZ_ASSERT(cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled());
// The protocol for creating a SAB requires the refcount to be
// incremented prior to the SAB creation.
SharedArrayRawBuffer* buf = mbx->val.sarb.buffer; SharedArrayRawBuffer* buf = mbx->val.sarb.buffer;
uint32_t length = mbx->val.sarb.length; uint32_t length = mbx->val.sarb.length;
if (!buf->addReference()) { if (!buf->addReference()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SC_SAB_REFCNT_OFLO); JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SC_SAB_REFCNT_OFLO);
return false; return false;
} }
auto dropBuf = MakeScopeExit([buf] { buf->dropReference(); });
// If the allocation fails we must decrement the refcount before
// returning.
Rooted<ArrayBufferObjectMaybeShared*> maybesab(cx, SharedArrayBufferObject::New(cx, buf, length)); Rooted<ArrayBufferObjectMaybeShared*> maybesab(cx, SharedArrayBufferObject::New(cx, buf, length));
if (!maybesab) { if (!maybesab) {
buf->dropReference();
return false; return false;
} }
// At this point the SAB was created successfully and it owns the
// refcount-increase on the buffer that we performed above. So even
// if we fail to allocate along any path below we must not decrement
// the refcount; the garbage collector must be allowed to handle
// that via finalization of the orphaned SAB object.
if (mbx->tag == MailboxTag::SharedArrayBuffer) { if (mbx->tag == MailboxTag::SharedArrayBuffer) {
newObj = maybesab; newObj = maybesab;
} else { } else {
if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_WebAssembly)) { if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_WebAssembly)) {
return false; return false;
} }
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmMemory).toObject()); RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmMemory).toObject());
newObj = WasmMemoryObject::create(cx, maybesab, proto); newObj = WasmMemoryObject::create(cx, maybesab, proto);
MOZ_ASSERT_IF(newObj, newObj->as<WasmMemoryObject>().isShared()); MOZ_ASSERT_IF(newObj, newObj->as<WasmMemoryObject>().isShared());
}
if (!newObj) { if (!newObj) {
return false; return false;
} }
}
dropBuf.release();
break; break;
} }