mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 826581 - Root RegExp source for the lifetime of RegExpShared. r=dvander
This commit is contained in:
parent
152a9285ce
commit
c570fc3be6
@ -143,7 +143,7 @@ js::ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
|
||||
Handle<JSStableString*> input, StableCharPtr chars, size_t length,
|
||||
size_t *lastIndex, JSBool test, jsval *rval)
|
||||
{
|
||||
RegExpGuard shared;
|
||||
RegExpGuard shared(cx);
|
||||
if (!reobj.getShared(cx, &shared))
|
||||
return false;
|
||||
|
||||
@ -252,7 +252,7 @@ CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
|
||||
*/
|
||||
RegExpFlag flags;
|
||||
{
|
||||
RegExpGuard g;
|
||||
RegExpGuard g(cx);
|
||||
if (!RegExpToShared(cx, *sourceObj, &g))
|
||||
return false;
|
||||
|
||||
@ -556,7 +556,7 @@ js::ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string, Match
|
||||
/* Step 1 (b) was performed by CallNonGenericMethod. */
|
||||
Rooted<RegExpObject*> reobj(cx, ®exp->asRegExp());
|
||||
|
||||
RegExpGuard re;
|
||||
RegExpGuard re(cx);
|
||||
if (!reobj->getShared(cx, &re))
|
||||
return RegExpRunStatus_Error;
|
||||
|
||||
|
12
js/src/jit-test/tests/basic/bug826581.js
Normal file
12
js/src/jit-test/tests/basic/bug826581.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Don't crash.
|
||||
|
||||
try {
|
||||
x = " () ";
|
||||
for (var y = 0; y < 19; y++) {
|
||||
x += x;
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
"".replace(x, "", "gy");
|
||||
} catch (e) { }
|
@ -1548,7 +1548,9 @@ class StringRegExpGuard
|
||||
}
|
||||
|
||||
public:
|
||||
StringRegExpGuard(JSContext *cx) : fm(cx) {}
|
||||
StringRegExpGuard(JSContext *cx)
|
||||
: re_(cx), fm(cx)
|
||||
{ }
|
||||
|
||||
/* init must succeed in order to call tryFlatMatch or normalizeRegExp. */
|
||||
bool init(JSContext *cx, CallArgs args, bool convertVoid = false)
|
||||
@ -1632,7 +1634,7 @@ class StringRegExpGuard
|
||||
opt = NULL;
|
||||
}
|
||||
|
||||
JSAtom *patstr;
|
||||
Rooted<JSAtom *> patstr(cx);
|
||||
if (flat) {
|
||||
patstr = flattenPattern(cx, fm.patstr);
|
||||
if (!patstr)
|
||||
@ -2784,7 +2786,7 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp)
|
||||
}
|
||||
|
||||
/* Step 8. */
|
||||
RegExpGuard re;
|
||||
RegExpGuard re(cx);
|
||||
JSLinearString *sepstr = NULL;
|
||||
bool sepDefined = args.hasDefined(0);
|
||||
if (sepDefined) {
|
||||
|
@ -7014,7 +7014,7 @@ mjit::Compiler::jsop_regexp()
|
||||
* between now and construction of that jitcode could purge the shared
|
||||
* info, but such activity will also abort compilation.
|
||||
*/
|
||||
RegExpGuard g;
|
||||
RegExpGuard g(cx);
|
||||
if (!reobj->getShared(cx, &g))
|
||||
return false;
|
||||
|
||||
|
@ -1659,6 +1659,11 @@ JITChunk::trace(JSTracer *trc)
|
||||
/* We use a manual write barrier in destroyChunk. */
|
||||
MarkObjectUnbarriered(trc, &rootedTemplates_[i], "jitchunk_template");
|
||||
}
|
||||
|
||||
/* RegExpShared objects require the RegExp source string. */
|
||||
RegExpShared **rootedRegExps_ = rootedRegExps();
|
||||
for (size_t i = 0; i < nRootedRegExps; i++)
|
||||
rootedRegExps_[i]->trace(trc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -101,7 +101,7 @@ RegExpObjectBuilder::clone(Handle<RegExpObject *> other, Handle<RegExpObject *>
|
||||
return build(source, newFlags);
|
||||
}
|
||||
|
||||
RegExpGuard g;
|
||||
RegExpGuard g(cx);
|
||||
if (!other->getShared(cx, &g))
|
||||
return NULL;
|
||||
|
||||
@ -405,6 +405,12 @@ RegExpShared::~RegExpShared()
|
||||
js_delete<BytecodePattern>(bytecode);
|
||||
}
|
||||
|
||||
void
|
||||
RegExpShared::trace(JSTracer *trc)
|
||||
{
|
||||
MarkString(trc, &source, "regexpshared source");
|
||||
}
|
||||
|
||||
void
|
||||
RegExpShared::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
|
||||
{
|
||||
|
@ -120,11 +120,11 @@ class RegExpShared
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Source to the RegExp. Safe to hold: if the RegExpShared is active,
|
||||
* then at least one RegExpObject must be referencing the RegExpShared,
|
||||
* and the RegExpObject keeps alive the source JSAtom.
|
||||
* Source to the RegExp. The RegExpShared must either be protected by a
|
||||
* RegExpGuard, which handles rooting for stacky RegExpShareds,
|
||||
* or trace() must be explicitly called during marking.
|
||||
*/
|
||||
JSAtom * source;
|
||||
HeapPtrAtom source;
|
||||
RegExpFlag flags;
|
||||
unsigned parenCount;
|
||||
|
||||
@ -149,6 +149,8 @@ class RegExpShared
|
||||
RegExpShared(JSRuntime *rt, JSAtom *source, RegExpFlag flags);
|
||||
~RegExpShared();
|
||||
|
||||
void trace(JSTracer *trc);
|
||||
|
||||
/* Static functions to expose some Yarr logic. */
|
||||
static inline bool isJITRuntimeEnabled(JSContext *cx);
|
||||
static void reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error);
|
||||
@ -198,22 +200,41 @@ class RegExpShared
|
||||
class RegExpGuard
|
||||
{
|
||||
RegExpShared *re_;
|
||||
|
||||
/*
|
||||
* Prevent the RegExp source from being collected:
|
||||
* because RegExpShared objects compile at execution time, the source
|
||||
* must remain rooted for the active lifetime of the RegExpShared.
|
||||
*/
|
||||
RootedAtom source_;
|
||||
|
||||
RegExpGuard(const RegExpGuard &) MOZ_DELETE;
|
||||
void operator=(const RegExpGuard &) MOZ_DELETE;
|
||||
|
||||
public:
|
||||
RegExpGuard() : re_(NULL) {}
|
||||
RegExpGuard(RegExpShared &re) : re_(&re) {
|
||||
re_->incRef();
|
||||
}
|
||||
void init(RegExpShared &re) {
|
||||
JS_ASSERT(!re_);
|
||||
re_ = &re;
|
||||
RegExpGuard(JSContext *cx)
|
||||
: re_(NULL), source_(cx)
|
||||
{ }
|
||||
|
||||
RegExpGuard(JSContext *cx, RegExpShared &re)
|
||||
: re_(&re), source_(cx, re.source)
|
||||
{
|
||||
re_->incRef();
|
||||
}
|
||||
|
||||
~RegExpGuard() {
|
||||
if (re_)
|
||||
re_->decRef();
|
||||
}
|
||||
|
||||
public:
|
||||
void init(RegExpShared &re) {
|
||||
JS_ASSERT(!re_);
|
||||
re_ = &re;
|
||||
re_->incRef();
|
||||
source_ = re.source;
|
||||
}
|
||||
|
||||
bool initialized() const { return !!re_; }
|
||||
RegExpShared *re() const { JS_ASSERT(initialized()); return re_; }
|
||||
RegExpShared *operator->() { return re(); }
|
||||
|
@ -87,7 +87,7 @@ RegExpStatics::executeLazy(JSContext *cx)
|
||||
StableCharPtr chars(matchesInput->chars(), length);
|
||||
|
||||
/* Execute the full regular expression. */
|
||||
RegExpGuard shared;
|
||||
RegExpGuard shared(cx);
|
||||
if (!regexp->getShared(cx, &shared))
|
||||
return false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user