Bug 1013586 - Detect and immediately crash on cross compartment bugs in RegExpShared, r=billm.

This commit is contained in:
Brian Hackett 2014-06-09 16:15:55 -06:00
parent d297a26703
commit 4fcf086b5c
2 changed files with 29 additions and 4 deletions

View File

@ -435,8 +435,8 @@ RegExpObject::toString(JSContext *cx) const
/* RegExpShared */
RegExpShared::RegExpShared(JSAtom *source, RegExpFlag flags)
: source(source), flags(flags), parenCount(0), canStringMatch(false), marked_(false)
RegExpShared::RegExpShared(JSCompartment *comp, JSAtom *source, RegExpFlag flags)
: comp(comp), source(source), flags(flags), parenCount(0), canStringMatch(false), marked_(false)
{
#ifdef JS_YARR
bytecode = nullptr;
@ -558,6 +558,9 @@ RegExpShared::compile(JSContext *cx, bool matchOnly, const jschar *sampleChars,
bool
RegExpShared::compile(JSContext *cx, HandleAtom pattern, bool matchOnly, const jschar *sampleChars, size_t sampleLength)
{
if (cx->compartment() != comp)
MOZ_CRASH();
if (!ignoreCase() && !StringHasRegExpMetaChars(pattern->chars(), pattern->length())) {
canStringMatch = true;
parenCount = 0;
@ -629,6 +632,9 @@ RegExpShared::compile(JSContext *cx, HandleAtom pattern, bool matchOnly, const j
#ifdef JS_ION
JS_ASSERT(!code.jitCode || !code.byteCode);
jitCode = code.jitCode;
if (jitCode && jitCode->tenuredZone() != comp->zone())
MOZ_CRASH();
#endif
byteCode = code.byteCode;
@ -970,6 +976,9 @@ RegExpCompartment::sweep(JSRuntime *rt)
for (Set::Enum e(set_); !e.empty(); e.popFront()) {
RegExpShared *shared = e.front();
if (this != &shared->compartment()->regExps)
MOZ_CRASH();
// Sometimes RegExpShared instances are marked without the
// compartment being subsequently cleared. This can happen if a GC is
// restarted while in progress (i.e. performing a full GC in the
@ -1002,6 +1011,9 @@ RegExpCompartment::sweep(JSRuntime *rt)
bool
RegExpCompartment::get(JSContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g)
{
if (this != &cx->compartment()->regExps)
MOZ_CRASH();
Key key(source, flags);
Set::AddPtr p = set_.lookupForAdd(key);
if (p) {
@ -1009,11 +1021,14 @@ RegExpCompartment::get(JSContext *cx, JSAtom *source, RegExpFlag flags, RegExpGu
// from the table (which only holds weak references).
MaybeTraceRegExpShared(cx, *p);
if ((*p)->compartment() != cx->compartment())
MOZ_CRASH();
g->init(**p);
return true;
}
ScopedJSDeletePtr<RegExpShared> shared(cx->new_<RegExpShared>(source, flags));
ScopedJSDeletePtr<RegExpShared> shared(cx->new_<RegExpShared>(cx->compartment(), source, flags));
if (!shared)
return false;

View File

@ -122,6 +122,8 @@ class RegExpShared
#endif
#endif
JSCompartment *comp;
/* Source to the RegExp, for lazy compilation. */
HeapPtrAtom source;
@ -161,7 +163,7 @@ class RegExpShared
#endif
public:
RegExpShared(JSAtom *source, RegExpFlag flags);
RegExpShared(JSCompartment *comp, JSAtom *source, RegExpFlag flags);
~RegExpShared();
#ifdef JS_YARR
@ -200,6 +202,10 @@ class RegExpShared
/* Accessors */
JSCompartment *compartment() const {
return comp;
}
size_t getParenCount() const {
JS_ASSERT(isCompiled(true) || isCompiled(false) || canStringMatch);
return parenCount;
@ -457,6 +463,10 @@ class RegExpObject : public JSObject
void setShared(RegExpShared &shared) {
JS_ASSERT(!maybeShared());
if (maybeShared())
MOZ_CRASH();
if (shared.compartment() != compartment())
MOZ_CRASH();
JSObject::setPrivate(&shared);
}