Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Unified Diff: src/runtime/runtime-regexp.cc

Issue 2791183002: [regexp] Throw on invalid capture group names in replacer string (Closed)
Patch Set: Typo Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.cc ('k') | src/runtime/runtime-strings.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime/runtime-regexp.cc
diff --git a/src/runtime/runtime-regexp.cc b/src/runtime/runtime-regexp.cc
index df9f52aa59e937c9e25908ad02baae5cb2662c8c..4a89b92396df7259e1ffd47f79fab99e57a36b22 100644
--- a/src/runtime/runtime-regexp.cc
+++ b/src/runtime/runtime-regexp.cc
@@ -75,7 +75,6 @@ class CompiledReplacement {
SUBJECT_CAPTURE,
REPLACEMENT_SUBSTRING,
REPLACEMENT_STRING,
- EMPTY,
NUMBER_OF_PART_TYPES
};
@@ -100,7 +99,6 @@ class CompiledReplacement {
DCHECK(to > from);
return ReplacementPart(-from, to);
}
- static inline ReplacementPart Empty() { return ReplacementPart(EMPTY, 0); }
// If tag <= 0 then it is the negation of a start index of a substring of
// the replacement pattern, otherwise it's a value from PartType.
@@ -113,8 +111,7 @@ class CompiledReplacement {
int tag;
// The data value's interpretation depends on the value of tag:
// tag == SUBJECT_PREFIX ||
- // tag == SUBJECT_SUFFIX ||
- // tag == EMPTY: data is unused.
+ // tag == SUBJECT_SUFFIX: data is unused.
// tag == SUBJECT_CAPTURE: data is the number of the capture.
// tag == REPLACEMENT_SUBSTRING ||
// tag == REPLACEMENT_STRING: data is index into array of substrings
@@ -251,30 +248,27 @@ class CompiledReplacement {
// Let capture be ? Get(namedCaptures, groupName).
- int capture_index = LookupNamedCapture(
+ const int capture_index = LookupNamedCapture(
[=](String* capture_name) {
return capture_name->IsEqualTo(requested_name);
},
capture_name_map);
+ // If ? HasProperty(_namedCaptures_, _groupName_) is *false*, throw
+ // a *SyntaxError* exception.
+ if (capture_index == -1) return Nothing<bool>();
+
// If capture is undefined, replace the text through the following
// '>' with the empty string.
// Otherwise, replace the text through the following '>' with
// ? ToString(capture).
- DCHECK_IMPLIES(
- capture_index != -1,
- 1 <= capture_index && capture_index <= capture_count);
-
- ReplacementPart replacement =
- (capture_index == -1)
- ? ReplacementPart::Empty()
- : ReplacementPart::SubjectCapture(capture_index);
+ DCHECK(1 <= capture_index && capture_index <= capture_count);
if (i > last) {
parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
}
- parts->Add(replacement, zone);
+ parts->Add(ReplacementPart::SubjectCapture(capture_index), zone);
last = closing_bracket_index + 1;
i = closing_bracket_index;
break;
@@ -386,8 +380,6 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
case REPLACEMENT_STRING:
builder->AddString(replacement_substrings_[part.data]);
break;
- case EMPTY:
- break;
default:
UNREACHABLE();
}
@@ -1018,19 +1010,32 @@ class MatchInfoBackedMatch : public String::Match {
}
MaybeHandle<String> GetNamedCapture(Handle<String> name,
- bool* capture_exists) override {
+ CaptureState* state) override {
DCHECK(has_named_captures_);
const int capture_index = LookupNamedCapture(
[=](String* capture_name) { return capture_name->Equals(*name); },
*capture_name_map_);
if (capture_index == -1) {
- *capture_exists = false;
+ *state = INVALID;
return name; // Arbitrary string handle.
}
DCHECK(1 <= capture_index && capture_index <= CaptureCount());
- return GetCapture(capture_index, capture_exists);
+
+ bool capture_exists;
+ Handle<String> capture_value;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate_, capture_value,
+ GetCapture(capture_index, &capture_exists),
+ String);
+
+ if (!capture_exists) {
+ *state = UNMATCHED;
+ return isolate_->factory()->empty_string();
+ } else {
+ *state = MATCHED;
+ return capture_value;
+ }
}
private:
@@ -1086,16 +1091,26 @@ class VectorBackedMatch : public String::Match {
}
MaybeHandle<String> GetNamedCapture(Handle<String> name,
- bool* capture_exists) override {
+ CaptureState* state) override {
DCHECK(has_named_captures_);
+
+ Maybe<bool> maybe_capture_exists =
+ JSReceiver::HasProperty(groups_obj_, name);
+ if (maybe_capture_exists.IsNothing()) return MaybeHandle<String>();
+
+ if (!maybe_capture_exists.FromJust()) {
+ *state = INVALID;
+ return name; // Arbitrary string handle.
+ }
+
Handle<Object> capture_obj;
ASSIGN_RETURN_ON_EXCEPTION(isolate_, capture_obj,
Object::GetProperty(groups_obj_, name), String);
if (capture_obj->IsUndefined(isolate_)) {
- *capture_exists = false;
- return name;
+ *state = UNMATCHED;
+ return isolate_->factory()->empty_string();
} else {
- *capture_exists = true;
+ *state = MATCHED;
return Object::ToString(isolate_, capture_obj);
}
}
@@ -1892,7 +1907,6 @@ RUNTIME_FUNCTION(Runtime_RegExpReplace) {
} else {
DCHECK(!functional_replace);
if (!groups_obj->IsUndefined(isolate)) {
- // TODO(jgruber): Behavior in this case is not yet specced.
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, groups_obj, JSReceiver::ToObject(isolate, groups_obj));
}
« no previous file with comments | « src/objects.cc ('k') | src/runtime/runtime-strings.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698