From f3b4178593bc891c6a65e58c44e7f5474a2b4f79 Mon Sep 17 00:00:00 2001 From: Lars T Hansen Date: Tue, 2 Oct 2018 14:12:41 +0200 Subject: [PATCH] Bug 1495573 - avoid double refcount decrement along failure path. r=luke --HG-- extra : rebase_source : 0894f81f9828fd41a35dbd8c9ccbdfbea4ba58b2 extra : histedit_source : 383355a2244dfba407b54c0e2e1627f9b2a44784 --- js/src/shell/js.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index c2585105a8c0..a8342b35a986 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -6686,34 +6686,44 @@ GetSharedObject(JSContext* cx, unsigned argc, Value* vp) // Flag was set in the sender; ensure it is set in the receiver. 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; uint32_t length = mbx->val.sarb.length; if (!buf->addReference()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SC_SAB_REFCNT_OFLO); return false; } - auto dropBuf = MakeScopeExit([buf] { buf->dropReference(); }); + + // If the allocation fails we must decrement the refcount before + // returning. Rooted maybesab(cx, SharedArrayBufferObject::New(cx, buf, length)); if (!maybesab) { + buf->dropReference(); 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) { newObj = maybesab; } else { if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_WebAssembly)) { return false; } - RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmMemory).toObject()); newObj = WasmMemoryObject::create(cx, maybesab, proto); MOZ_ASSERT_IF(newObj, newObj->as().isShared()); + if (!newObj) { + return false; + } } - if (!newObj) { - return false; - } - - dropBuf.release(); break; }