From ddee007ca851ca3ae9ae1949507a1ca26b2baf6e Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 13 Jul 2015 20:20:29 -0700 Subject: [PATCH] Bug 1180536 - Use mozilla::ScopeExit to clean up Debugger::addDebuggeeGlobal's consistency on failure; r=sfink --- js/src/vm/Debugger.cpp | 113 +++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 50 deletions(-) diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 69c19f02ed6..ad3e1ddadc8 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -7,6 +7,7 @@ #include "vm/Debugger-inl.h" #include "mozilla/DebugOnly.h" +#include "mozilla/ScopeExit.h" #include "jscntxt.h" #include "jscompartment.h" @@ -46,6 +47,7 @@ using JS::dbg::Builder; using js::frontend::IsIdentifier; using mozilla::ArrayLength; using mozilla::DebugOnly; +using mozilla::MakeScopeExit; using mozilla::Maybe; using mozilla::UniquePtr; @@ -3298,75 +3300,86 @@ Debugger::addDebuggeeGlobal(JSContext* cx, Handle global) /* * For global to become this js::Debugger's debuggee: * - * 1. global must be in this->debuggees, - * 2. this js::Debugger must be in global->getDebuggers(), + * 1. this js::Debugger must be in global->getDebuggers(), + * 2. global must be in this->debuggees, * 3. it must be in zone->getDebuggers(), - * 4. JSCompartment::isDebuggee()'s bit must be set, and + * 4. the debuggee's zone must be in this->debuggeeZones, * 5. if we are tracking allocations, the SavedStacksMetadataCallback must be - * installed for this compartment. + * installed for this compartment, and + * 6. JSCompartment::isDebuggee()'s bit must be set. * - * All five indications must be kept consistent. + * All six indications must be kept consistent. */ - bool inDebuggees = false; - bool inGlobalDebuggers = false; - bool inZoneDebuggers = false; - bool inDebuggeeZones = false; - AutoCompartment ac(cx, global); Zone* zone = global->zone(); + // (1) auto* globalDebuggers = GlobalObject::getOrCreateDebuggers(cx, global); if (!globalDebuggers) - goto error; - if (!globalDebuggers->append(this)) - goto oom; - inGlobalDebuggers = true; - - if (!debuggees.put(global)) - goto oom; - inDebuggees = true; - - Zone::DebuggerVector* zoneDebuggers; - if (!debuggeeZones.has(zone)) { - zoneDebuggers = zone->getOrCreateDebuggers(cx); - if (!zoneDebuggers) - goto error; - if (!zoneDebuggers->append(this)) - goto oom; - inZoneDebuggers = true; - - if (!debuggeeZones.put(zone)) - goto oom; - inDebuggeeZones = true; + return false; + if (!globalDebuggers->append(this)) { + ReportOutOfMemory(cx); + return false; } + auto globalDebuggersGuard = MakeScopeExit([&] { + globalDebuggers->popBack(); + }); + // (2) + if (!debuggees.put(global)) { + ReportOutOfMemory(cx); + return false; + } + auto debuggeesGuard = MakeScopeExit([&] { + debuggees.remove(global); + }); + + bool addingZoneRelation = !debuggeeZones.has(zone); + + // (3) + auto* zoneDebuggers = zone->getOrCreateDebuggers(cx); + if (!zoneDebuggers) + return false; + if (addingZoneRelation && !zoneDebuggers->append(this)) { + ReportOutOfMemory(cx); + return false; + } + auto zoneDebuggersGuard = MakeScopeExit([&] { + if (addingZoneRelation) + zoneDebuggers->popBack(); + }); + + // (4) + if (addingZoneRelation && !debuggeeZones.put(zone)) { + ReportOutOfMemory(cx); + return false; + } + auto debuggeeZonesGuard = MakeScopeExit([&] { + if (addingZoneRelation) + debuggeeZones.remove(zone); + }); + + // (5) if (trackingAllocationSites && !Debugger::addAllocationsTracking(cx, *global)) - goto error; + return false; + auto allocationsTrackingGuard = MakeScopeExit([&] { + if (trackingAllocationSites) + Debugger::removeAllocationsTracking(*global); + }); + // (6) debuggeeCompartment->setIsDebuggee(); debuggeeCompartment->updateDebuggerObservesAsmJS(); - if (observesAllExecution() && !ensureExecutionObservabilityOfCompartment(cx, debuggeeCompartment)) - goto error; + return false; + globalDebuggersGuard.release(); + debuggeesGuard.release(); + zoneDebuggersGuard.release(); + debuggeeZonesGuard.release(); + allocationsTrackingGuard.release(); return true; - - oom: - ReportOutOfMemory(cx); - // Fall through... - - error: - // Maintain consistency on error. - if (inGlobalDebuggers) - globalDebuggers->popBack(); - if (inDebuggees) - debuggees.remove(global); - if (inZoneDebuggers) - zoneDebuggers->popBack(); - if (inDebuggeeZones) - debuggeeZones.remove(zone); - return false; } bool