Fix regexp match pair end-index == -1 assumption. (r=dmandelin, a=blocker b=605754)

--HG--
extra : rebase_source : a4a73855736671e4dae8264522ce26a3505ab800
This commit is contained in:
Chris Leary 2010-12-01 16:33:49 -08:00
Родитель b659ccd1b7
Коммит de67205f5f
3 изменённых файлов: 31 добавлений и 20 удалений

Просмотреть файл

@ -0,0 +1,2 @@
var result = "foobarbaz".replace(/foo(bar)?bar/, "$1");
assertEq(result, "baz");

Просмотреть файл

@ -124,7 +124,9 @@ class RegExpStatics
JS_ASSERT(matchPairsInput);
size_t mpiLen = matchPairsInput->length();
/* Both members of the first pair must be non-negative. */
JS_ASSERT(pairIsPresent(0));
JS_ASSERT(get(0, 1) >= 0);
/* Present pairs must be valid. */
for (size_t i = 0; i < pairCount(); ++i) {
@ -137,6 +139,19 @@ class RegExpStatics
#endif
}
bool pairIsPresent(size_t pairNum) const {
return getCrash(pairNum, 0) >= 0;
}
/* Precondition: paren is present. */
size_t getParenLength(size_t parenNum) const {
size_t pairNum = parenNum + 1;
if (pairCountCrash() <= pairNum)
return 0;
JS_CRASH_UNLESS(pairIsPresent(pairNum));
return getCrash(pairNum, 1) - getCrash(pairNum, 0);
}
int get(size_t pairNum, bool which) const {
JS_ASSERT(pairNum < pairCount());
return matchPairs[2 * pairNum + which];
@ -168,10 +183,6 @@ class RegExpStatics
/* Mutators. */
/*
* The inputOffset parameter is added to the present (i.e. non-negative) match items to emulate
* sticky mode.
*/
bool updateFromMatch(JSContext *cx, JSString *input, int *buf, size_t matchItemCount) {
aboutToWrite();
pendingInput = input;
@ -204,8 +215,6 @@ class RegExpStatics
matchPairs.clear();
}
bool pairIsPresent(size_t pairNum) { return get(0, 0) != -1; }
/* Corresponds to JSAPI functionality to set the pending RegExp input. */
void reset(JSString *newInput, bool newMultiline) {
aboutToWrite();
@ -238,12 +247,15 @@ class RegExpStatics
return size_t(limit);
}
/* Returns whether results for a non-empty match are present. */
bool matched() const {
JS_ASSERT(pairCount() > 0);
JS_ASSERT_IF(get(0, 1) == -1, get(1, 1) == -1);
return get(0, 1) - get(0, 0) > 0;
}
size_t getParenCount() const {
/* The first pair is the whole match. */
JS_ASSERT(pairCount() > 0);
return pairCount() - 1;
}
@ -255,12 +267,6 @@ class RegExpStatics
JS_CALL_STRING_TRACER(trc, matchPairsInput, "res->matchPairsInput");
}
size_t getParenLength(size_t parenNum) const {
if (pairCountCrash() <= parenNum + 1)
return 0;
return getCrash(parenNum + 1, 1) - getCrash(parenNum + 1, 0);
}
/* Value creators. */
bool createPendingInput(JSContext *cx, Value *out) const;
@ -275,6 +281,7 @@ class RegExpStatics
/* Substring creators. */
/* @param num Zero-indexed paren number (i.e. $1 is 0). */
void getParen(size_t num, JSSubString *out) const;
void getLastMatch(JSSubString *out) const;
void getLastParen(JSSubString *out) const;

Просмотреть файл

@ -265,7 +265,6 @@ RegExp::createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemC
} else {
/* Missing parenthesized match. */
JS_ASSERT(i != 0); /* Since we had a match, first pair must be present. */
JS_ASSERT(start == end && end == -1);
if (!builder.append(INT_TO_JSID(i / 2), UndefinedValue()))
return NULL;
}
@ -582,11 +581,11 @@ RegExpStatics::createLastParen(JSContext *cx, Value *out) const
int start = get(num, 0);
int end = get(num, 1);
if (start == -1) {
JS_ASSERT(end == -1);
out->setString(cx->runtime->emptyString);
return true;
}
JS_ASSERT(start >= 0 && end >= 0);
JS_ASSERT(end >= start);
return createDependent(cx, start, end, out);
}
@ -621,7 +620,12 @@ RegExpStatics::createRightContext(JSContext *cx, Value *out) const
inline void
RegExpStatics::getParen(size_t num, JSSubString *out) const
{
out->chars = matchPairsInput->chars() + getCrash(num + 1, 0);
size_t pairNum = num + 1;
if (!pairIsPresent(pairNum)) {
*out = js_EmptySubString;
return;
}
out->chars = matchPairsInput->chars() + getCrash(pairNum, 0);
out->length = getParenLength(num);
}
@ -641,14 +645,12 @@ RegExpStatics::getLastMatch(JSSubString *out) const
inline void
RegExpStatics::getLastParen(JSSubString *out) const
{
if (!pairCountCrash()) {
size_t parenCount = getParenCount();
if (!parenCount) {
*out = js_EmptySubString;
return;
}
size_t num = pairCount() - 1;
out->chars = matchPairsInput->chars() + getCrash(num, 0);
JS_CRASH_UNLESS(getCrash(num, 1) >= get(num, 0));
out->length = get(num, 1) - get(num, 0);
getParen(parenCount - 1, out);
}
inline void