Bug 1438310 - Remove ScopedMatchPairs and devirtualize MatchPairs to avoid triggering undefined behavior. r=jwalden

This commit is contained in:
Jan de Mooij 2018-03-01 21:32:45 +01:00
parent efd8bcc49b
commit de47aa59e3
5 changed files with 22 additions and 61 deletions

View File

@ -120,7 +120,7 @@ CreateRegExpSearchResult(const MatchPairs& matches)
*/
static RegExpRunStatus
ExecuteRegExpImpl(JSContext* cx, RegExpStatics* res, MutableHandleRegExpShared re,
HandleLinearString input, size_t searchIndex, MatchPairs* matches,
HandleLinearString input, size_t searchIndex, VectorMatchPairs* matches,
size_t* endIndex)
{
RegExpRunStatus status = RegExpShared::execute(cx, re, input, searchIndex, matches, endIndex);
@ -147,7 +147,7 @@ js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*>
if (!shared)
return false;
ScopedMatchPairs matches(&cx->tempLifoAlloc());
VectorMatchPairs matches;
RegExpRunStatus status = ExecuteRegExpImpl(cx, res, &shared, input, *lastIndex,
&matches, nullptr);
@ -904,7 +904,7 @@ IsTrailSurrogateWithLeadSurrogate(HandleLinearString input, int32_t index)
*/
static RegExpRunStatus
ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex,
MatchPairs* matches, size_t* endIndex)
VectorMatchPairs* matches, size_t* endIndex)
{
/*
* WARNING: Despite the presence of spec step comment numbers, this
@ -979,7 +979,7 @@ RegExpMatcherImpl(JSContext* cx, HandleObject regexp, HandleString string, int32
MutableHandleValue rval)
{
/* Execute regular expression and gather matches. */
ScopedMatchPairs matches(&cx->tempLifoAlloc());
VectorMatchPairs matches;
/* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */
RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches, nullptr);
@ -1048,7 +1048,7 @@ RegExpSearcherImpl(JSContext* cx, HandleObject regexp, HandleString string, int3
int32_t* result)
{
/* Execute regular expression and gather matches. */
ScopedMatchPairs matches(&cx->tempLifoAlloc());
VectorMatchPairs matches;
/* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */
RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches, nullptr);

View File

@ -51,7 +51,8 @@ struct MatchPair
}
};
/* Base class for RegExp execution output. */
// MachPairs is used as base class for VectorMatchPairs but can also be
// stack-allocated (without a Vector) in JIT code.
class MatchPairs
{
protected:
@ -72,10 +73,6 @@ class MatchPairs
friend class RegExpShared;
friend class RegExpStatics;
/* MatchPair buffer allocator: set pairs_ and pairCount_. */
virtual bool allocOrExpandArray(size_t pairCount) = 0;
bool initArrayFrom(MatchPairs& copyFrom);
void forgetArray() { pairs_ = nullptr; }
void checkAgainst(size_t inputLength) {
@ -114,37 +111,18 @@ class MatchPairs
}
};
/* MatchPairs allocated into temporary storage, removed when out of scope. */
class ScopedMatchPairs : public MatchPairs
{
LifoAllocScope lifoScope_;
public:
/* Constructs an implicit LifoAllocScope. */
explicit ScopedMatchPairs(LifoAlloc* lifoAlloc)
: lifoScope_(lifoAlloc)
{ }
protected:
bool allocOrExpandArray(size_t pairCount) override;
};
/*
* MatchPairs allocated into permanent storage, for RegExpStatics.
* The Vector of MatchPairs is reusable by Vector expansion.
*/
class VectorMatchPairs : public MatchPairs
{
Vector<MatchPair, 10, SystemAllocPolicy> vec_;
public:
VectorMatchPairs() {
vec_.clear();
}
protected:
friend class RegExpShared;
friend class RegExpStatics;
bool allocOrExpandArray(size_t pairCount) override;
/* MatchPair buffer allocator: set pairs_ and pairCount_. */
bool allocOrExpandArray(size_t pairCount);
bool initArrayFrom(VectorMatchPairs& copyFrom);
};
} /* namespace js */

View File

@ -70,7 +70,7 @@ js::RegExpAlloc(JSContext* cx, NewObjectKind newKind, HandleObject proto /* = nu
/* MatchPairs */
bool
MatchPairs::initArrayFrom(MatchPairs& copyFrom)
VectorMatchPairs::initArrayFrom(VectorMatchPairs& copyFrom)
{
MOZ_ASSERT(copyFrom.pairCount() > 0);
@ -82,29 +82,10 @@ MatchPairs::initArrayFrom(MatchPairs& copyFrom)
return true;
}
bool
ScopedMatchPairs::allocOrExpandArray(size_t pairCount)
{
/* Array expansion is forbidden, but array reuse is acceptable. */
if (pairCount_) {
MOZ_ASSERT(pairs_);
MOZ_ASSERT(pairCount_ == pairCount);
return true;
}
MOZ_ASSERT(!pairs_);
pairs_ = (MatchPair*)lifoScope_.alloc().alloc(sizeof(MatchPair) * pairCount);
if (!pairs_)
return false;
pairCount_ = pairCount;
return true;
}
bool
VectorMatchPairs::allocOrExpandArray(size_t pairCount)
{
if (!vec_.resizeUninitialized(sizeof(MatchPair) * pairCount))
if (!vec_.resizeUninitialized(pairCount))
return false;
pairs_ = &vec_[0];
@ -1082,7 +1063,7 @@ RegExpShared::compileIfNecessary(JSContext* cx, MutableHandleRegExpShared re,
/* static */ RegExpRunStatus
RegExpShared::execute(JSContext* cx, MutableHandleRegExpShared re, HandleLinearString input,
size_t start, MatchPairs* matches, size_t* endIndex)
size_t start, VectorMatchPairs* matches, size_t* endIndex)
{
MOZ_ASSERT_IF(matches, !endIndex);
MOZ_ASSERT_IF(!matches, endIndex);

View File

@ -28,10 +28,10 @@
namespace js {
class ArrayObject;
class MatchPairs;
class RegExpCompartment;
class RegExpShared;
class RegExpStatics;
class VectorMatchPairs;
using RootedRegExpShared = JS::Rooted<RegExpShared*>;
using HandleRegExpShared = JS::Handle<RegExpShared*>;
@ -159,7 +159,7 @@ class RegExpShared : public gc::TenuredCell
// matches if specified and otherwise only determining if there is a match.
static RegExpRunStatus execute(JSContext* cx, MutableHandleRegExpShared res,
HandleLinearString input, size_t searchIndex,
MatchPairs* matches, size_t* endIndex);
VectorMatchPairs* matches, size_t* endIndex);
// Register a table with this RegExpShared, and take ownership.
bool addTable(JitCodeTable table) {

View File

@ -62,7 +62,8 @@ class RegExpStatics
/* Mutators. */
inline void updateLazily(JSContext* cx, JSLinearString* input,
RegExpShared* shared, size_t lastIndex);
inline bool updateFromMatchPairs(JSContext* cx, JSLinearString* input, MatchPairs& newPairs);
inline bool updateFromMatchPairs(JSContext* cx, JSLinearString* input,
VectorMatchPairs& newPairs);
inline void clear();
@ -251,7 +252,8 @@ RegExpStatics::updateLazily(JSContext* cx, JSLinearString* input,
}
inline bool
RegExpStatics::updateFromMatchPairs(JSContext* cx, JSLinearString* input, MatchPairs& newPairs)
RegExpStatics::updateFromMatchPairs(JSContext* cx, JSLinearString* input,
VectorMatchPairs& newPairs)
{
MOZ_ASSERT(input);