Bug 691192 - JSAutoEnterCompartment::enter shouldn't malloc(). r=luke

This commit is contained in:
Justin Lebar 2011-10-04 15:25:18 -04:00
parent 930a45b1fb
commit 0aeafafb09
2 changed files with 48 additions and 18 deletions

View File

@ -1323,13 +1323,20 @@ JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call)
bool
JSAutoEnterCompartment::enter(JSContext *cx, JSObject *target)
{
JS_ASSERT(!call);
if (cx->compartment == target->compartment()) {
call = reinterpret_cast<JSCrossCompartmentCall*>(1);
JS_ASSERT(state == STATE_UNENTERED);
if (cx->compartment == target->getCompartment()) {
state = STATE_SAME_COMPARTMENT;
return true;
}
call = JS_EnterCrossCompartmentCall(cx, target);
return call != NULL;
JS_STATIC_ASSERT(sizeof(bytes) == sizeof(AutoCompartment));
CHECK_REQUEST(cx);
AutoCompartment *call = new (bytes) AutoCompartment(cx, target);
if (call->enter()) {
state = STATE_OTHER_COMPARTMENT;
return true;
}
return false;
}
void
@ -1338,6 +1345,15 @@ JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext *cx, JSObject *target)
(void) enter(cx, target);
}
JSAutoEnterCompartment::~JSAutoEnterCompartment()
{
if (state == STATE_OTHER_COMPARTMENT) {
AutoCompartment* ac = reinterpret_cast<AutoCompartment*>(bytes);
CHECK_REQUEST(ac->context);
ac->~AutoCompartment();
}
}
namespace JS {
bool

View File

@ -2214,27 +2214,41 @@ JS_END_EXTERN_C
class JS_PUBLIC_API(JSAutoEnterCompartment)
{
JSCrossCompartmentCall *call;
/*
* This is a poor man's Maybe<AutoCompartment>, because we don't have
* access to the AutoCompartment definition here. We statically assert in
* jsapi.cpp that we have the right size here.
*/
#ifndef _MSC_VER
void* bytes[13];
#else
void* bytes[sizeof(void*) == 4 ? 16 : 13];
#endif
/*
* This object may be in one of three states. If enter() or
* enterAndIgnoreErrors() hasn't been called, it's in STATE_UNENTERED.
* Otherwise, if we were asked to enter into the current compartment, our
* state is STATE_SAME_COMPARTMENT. If we actually created an
* AutoCompartment and entered another compartment, our state is
* STATE_OTHER_COMPARTMENT.
*/
enum State {
STATE_UNENTERED,
STATE_SAME_COMPARTMENT,
STATE_OTHER_COMPARTMENT
} state;
public:
JSAutoEnterCompartment() : call(NULL) {}
JSAutoEnterCompartment() : state(STATE_UNENTERED) {}
bool enter(JSContext *cx, JSObject *target);
void enterAndIgnoreErrors(JSContext *cx, JSObject *target);
bool entered() const { return call != NULL; }
bool entered() const { return state != STATE_UNENTERED; }
~JSAutoEnterCompartment() {
if (call && call != reinterpret_cast<JSCrossCompartmentCall*>(1))
JS_LeaveCrossCompartmentCall(call);
}
void swap(JSAutoEnterCompartment &other) {
JSCrossCompartmentCall *tmp = call;
call = other.call;
other.call = tmp;
}
~JSAutoEnterCompartment();
};
JS_BEGIN_EXTERN_C