[regexp] Clone match info for match indices.

The current behavior for generating match indices simply stashes a
pointer to the match info and then constructs the indices lazily.
However, it turns out the match info object used to create the result
object is the regexp_last_match_info living on native context, and thus
it can change between the creation of the result object and the generation
of indices. This cl clones the match info which will be safer.

Bug: v8:9548
Change-Id: Ia6f26f88fbc22fd09671bf4c579d39a1510b552d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1864585
Commit-Queue: Joshua Litt <joshualitt@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64356}
This commit is contained in:
Joshua Litt 2019-10-17 07:15:10 -07:00 committed by Commit Bot
parent 719c6e7c1f
commit dfd9ceb984
2 changed files with 20 additions and 3 deletions

View File

@ -84,6 +84,14 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::AllocateRegExpResult(
length, SmiConstant(JSArray::kMaxFastArrayLength)));
CSA_ASSERT(this, SmiGreaterThan(length, SmiConstant(0)));
// Clone the match info so we can stash a pointer to it. This is necessary
// because it may point to the 'regexp_last_match_info' on native context and
// thus could change.
// TODO(v8:9870): Now that we clone the last match info, we can make its size
// static.
TNode<FixedArrayBase> cloned_match_info =
CloneFixedArray(match_info, ExtractFixedArrayFlag::kFixedArrays);
// Allocate.
const ElementsKind elements_kind = PACKED_ELEMENTS;
@ -117,10 +125,10 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::AllocateRegExpResult(
StoreObjectFieldNoWriteBarrier(result, JSRegExpResult::kNamesOffset,
undefined_value);
// Stash match_info in order to build JSRegExpResultIndices lazily when the
// 'indices' property is accessed.
// Stash cloned_match_info in order to build JSRegExpResultIndices lazily when
// the 'indices' property is accessed.
StoreObjectField(result, JSRegExpResult::kCachedIndicesOrMatchInfoOffset,
match_info);
cloned_match_info);
// Finish elements initialization.

View File

@ -103,3 +103,12 @@
assertEquals(m.indices.groups, {'Z': [4, 5]})
}
// Match between matches.
{
const re = /a+(?<A>zz)?(?<B>ii)?/;
const m = re.exec("xaaazzii");
assertTrue(/b+(?<C>cccc)?/.test("llllllbbbbbbcccc"));
assertEquals(m.indices, [[1, 8], [4, 6], [6, 8]]);
assertEquals(m.indices.groups, {'A': [4, 6], 'B': [6, 8]});
}