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

Side by Side 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, 8 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 unified diff | Download patch
« no previous file with comments | « src/objects.cc ('k') | src/runtime/runtime-strings.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/runtime/runtime-utils.h" 5 #include "src/runtime/runtime-utils.h"
6 6
7 #include <functional> 7 #include <functional>
8 8
9 #include "src/arguments.h" 9 #include "src/arguments.h"
10 #include "src/conversions-inl.h" 10 #include "src/conversions-inl.h"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 68
69 Zone* zone() const { return zone_; } 69 Zone* zone() const { return zone_; }
70 70
71 private: 71 private:
72 enum PartType { 72 enum PartType {
73 SUBJECT_PREFIX = 1, 73 SUBJECT_PREFIX = 1,
74 SUBJECT_SUFFIX, 74 SUBJECT_SUFFIX,
75 SUBJECT_CAPTURE, 75 SUBJECT_CAPTURE,
76 REPLACEMENT_SUBSTRING, 76 REPLACEMENT_SUBSTRING,
77 REPLACEMENT_STRING, 77 REPLACEMENT_STRING,
78 EMPTY,
79 NUMBER_OF_PART_TYPES 78 NUMBER_OF_PART_TYPES
80 }; 79 };
81 80
82 struct ReplacementPart { 81 struct ReplacementPart {
83 static inline ReplacementPart SubjectMatch() { 82 static inline ReplacementPart SubjectMatch() {
84 return ReplacementPart(SUBJECT_CAPTURE, 0); 83 return ReplacementPart(SUBJECT_CAPTURE, 0);
85 } 84 }
86 static inline ReplacementPart SubjectCapture(int capture_index) { 85 static inline ReplacementPart SubjectCapture(int capture_index) {
87 return ReplacementPart(SUBJECT_CAPTURE, capture_index); 86 return ReplacementPart(SUBJECT_CAPTURE, capture_index);
88 } 87 }
89 static inline ReplacementPart SubjectPrefix() { 88 static inline ReplacementPart SubjectPrefix() {
90 return ReplacementPart(SUBJECT_PREFIX, 0); 89 return ReplacementPart(SUBJECT_PREFIX, 0);
91 } 90 }
92 static inline ReplacementPart SubjectSuffix(int subject_length) { 91 static inline ReplacementPart SubjectSuffix(int subject_length) {
93 return ReplacementPart(SUBJECT_SUFFIX, subject_length); 92 return ReplacementPart(SUBJECT_SUFFIX, subject_length);
94 } 93 }
95 static inline ReplacementPart ReplacementString() { 94 static inline ReplacementPart ReplacementString() {
96 return ReplacementPart(REPLACEMENT_STRING, 0); 95 return ReplacementPart(REPLACEMENT_STRING, 0);
97 } 96 }
98 static inline ReplacementPart ReplacementSubString(int from, int to) { 97 static inline ReplacementPart ReplacementSubString(int from, int to) {
99 DCHECK(from >= 0); 98 DCHECK(from >= 0);
100 DCHECK(to > from); 99 DCHECK(to > from);
101 return ReplacementPart(-from, to); 100 return ReplacementPart(-from, to);
102 } 101 }
103 static inline ReplacementPart Empty() { return ReplacementPart(EMPTY, 0); }
104 102
105 // If tag <= 0 then it is the negation of a start index of a substring of 103 // If tag <= 0 then it is the negation of a start index of a substring of
106 // the replacement pattern, otherwise it's a value from PartType. 104 // the replacement pattern, otherwise it's a value from PartType.
107 ReplacementPart(int tag, int data) : tag(tag), data(data) { 105 ReplacementPart(int tag, int data) : tag(tag), data(data) {
108 // Must be non-positive or a PartType value. 106 // Must be non-positive or a PartType value.
109 DCHECK(tag < NUMBER_OF_PART_TYPES); 107 DCHECK(tag < NUMBER_OF_PART_TYPES);
110 } 108 }
111 // Either a value of PartType or a non-positive number that is 109 // Either a value of PartType or a non-positive number that is
112 // the negation of an index into the replacement string. 110 // the negation of an index into the replacement string.
113 int tag; 111 int tag;
114 // The data value's interpretation depends on the value of tag: 112 // The data value's interpretation depends on the value of tag:
115 // tag == SUBJECT_PREFIX || 113 // tag == SUBJECT_PREFIX ||
116 // tag == SUBJECT_SUFFIX || 114 // tag == SUBJECT_SUFFIX: data is unused.
117 // tag == EMPTY: data is unused.
118 // tag == SUBJECT_CAPTURE: data is the number of the capture. 115 // tag == SUBJECT_CAPTURE: data is the number of the capture.
119 // tag == REPLACEMENT_SUBSTRING || 116 // tag == REPLACEMENT_SUBSTRING ||
120 // tag == REPLACEMENT_STRING: data is index into array of substrings 117 // tag == REPLACEMENT_STRING: data is index into array of substrings
121 // of the replacement string. 118 // of the replacement string.
122 // tag <= 0: Temporary representation of the substring of the replacement 119 // tag <= 0: Temporary representation of the substring of the replacement
123 // string ranging over -tag .. data. 120 // string ranging over -tag .. data.
124 // Is replaced by REPLACEMENT_{SUB,}STRING when we create the 121 // Is replaced by REPLACEMENT_{SUB,}STRING when we create the
125 // substring objects. 122 // substring objects.
126 int data; 123 int data;
127 }; 124 };
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 } 241 }
245 242
246 // Throw a SyntaxError for invalid replacement strings. 243 // Throw a SyntaxError for invalid replacement strings.
247 if (closing_bracket_index == -1) return Nothing<bool>(); 244 if (closing_bracket_index == -1) return Nothing<bool>();
248 245
249 Vector<Char> requested_name = 246 Vector<Char> requested_name =
250 characters.SubVector(name_start_index, closing_bracket_index); 247 characters.SubVector(name_start_index, closing_bracket_index);
251 248
252 // Let capture be ? Get(namedCaptures, groupName). 249 // Let capture be ? Get(namedCaptures, groupName).
253 250
254 int capture_index = LookupNamedCapture( 251 const int capture_index = LookupNamedCapture(
255 [=](String* capture_name) { 252 [=](String* capture_name) {
256 return capture_name->IsEqualTo(requested_name); 253 return capture_name->IsEqualTo(requested_name);
257 }, 254 },
258 capture_name_map); 255 capture_name_map);
259 256
257 // If ? HasProperty(_namedCaptures_, _groupName_) is *false*, throw
258 // a *SyntaxError* exception.
259 if (capture_index == -1) return Nothing<bool>();
260
260 // If capture is undefined, replace the text through the following 261 // If capture is undefined, replace the text through the following
261 // '>' with the empty string. 262 // '>' with the empty string.
262 // Otherwise, replace the text through the following '>' with 263 // Otherwise, replace the text through the following '>' with
263 // ? ToString(capture). 264 // ? ToString(capture).
264 265
265 DCHECK_IMPLIES( 266 DCHECK(1 <= capture_index && capture_index <= capture_count);
266 capture_index != -1,
267 1 <= capture_index && capture_index <= capture_count);
268
269 ReplacementPart replacement =
270 (capture_index == -1)
271 ? ReplacementPart::Empty()
272 : ReplacementPart::SubjectCapture(capture_index);
273 267
274 if (i > last) { 268 if (i > last) {
275 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone); 269 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
276 } 270 }
277 parts->Add(replacement, zone); 271 parts->Add(ReplacementPart::SubjectCapture(capture_index), zone);
278 last = closing_bracket_index + 1; 272 last = closing_bracket_index + 1;
279 i = closing_bracket_index; 273 i = closing_bracket_index;
280 break; 274 break;
281 } 275 }
282 default: 276 default:
283 i = next_index; 277 i = next_index;
284 break; 278 break;
285 } 279 }
286 } 280 }
287 } 281 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 int to = match[capture * 2 + 1]; 373 int to = match[capture * 2 + 1];
380 if (from >= 0 && to > from) { 374 if (from >= 0 && to > from) {
381 builder->AddSubjectSlice(from, to); 375 builder->AddSubjectSlice(from, to);
382 } 376 }
383 break; 377 break;
384 } 378 }
385 case REPLACEMENT_SUBSTRING: 379 case REPLACEMENT_SUBSTRING:
386 case REPLACEMENT_STRING: 380 case REPLACEMENT_STRING:
387 builder->AddString(replacement_substrings_[part.data]); 381 builder->AddString(replacement_substrings_[part.data]);
388 break; 382 break;
389 case EMPTY:
390 break;
391 default: 383 default:
392 UNREACHABLE(); 384 UNREACHABLE();
393 } 385 }
394 } 386 }
395 } 387 }
396 388
397 void FindOneByteStringIndices(Vector<const uint8_t> subject, uint8_t pattern, 389 void FindOneByteStringIndices(Vector<const uint8_t> subject, uint8_t pattern,
398 List<int>* indices, unsigned int limit) { 390 List<int>* indices, unsigned int limit) {
399 DCHECK(limit > 0); 391 DCHECK(limit > 0);
400 // Collect indices of pattern in subject using memchr. 392 // Collect indices of pattern in subject using memchr.
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 } 1003 }
1012 1004
1013 MaybeHandle<String> GetCapture(int i, bool* capture_exists) override { 1005 MaybeHandle<String> GetCapture(int i, bool* capture_exists) override {
1014 Handle<Object> capture_obj = RegExpUtils::GenericCaptureGetter( 1006 Handle<Object> capture_obj = RegExpUtils::GenericCaptureGetter(
1015 isolate_, match_info_, i, capture_exists); 1007 isolate_, match_info_, i, capture_exists);
1016 return (*capture_exists) ? Object::ToString(isolate_, capture_obj) 1008 return (*capture_exists) ? Object::ToString(isolate_, capture_obj)
1017 : isolate_->factory()->empty_string(); 1009 : isolate_->factory()->empty_string();
1018 } 1010 }
1019 1011
1020 MaybeHandle<String> GetNamedCapture(Handle<String> name, 1012 MaybeHandle<String> GetNamedCapture(Handle<String> name,
1021 bool* capture_exists) override { 1013 CaptureState* state) override {
1022 DCHECK(has_named_captures_); 1014 DCHECK(has_named_captures_);
1023 const int capture_index = LookupNamedCapture( 1015 const int capture_index = LookupNamedCapture(
1024 [=](String* capture_name) { return capture_name->Equals(*name); }, 1016 [=](String* capture_name) { return capture_name->Equals(*name); },
1025 *capture_name_map_); 1017 *capture_name_map_);
1026 1018
1027 if (capture_index == -1) { 1019 if (capture_index == -1) {
1028 *capture_exists = false; 1020 *state = INVALID;
1029 return name; // Arbitrary string handle. 1021 return name; // Arbitrary string handle.
1030 } 1022 }
1031 1023
1032 DCHECK(1 <= capture_index && capture_index <= CaptureCount()); 1024 DCHECK(1 <= capture_index && capture_index <= CaptureCount());
1033 return GetCapture(capture_index, capture_exists); 1025
1026 bool capture_exists;
1027 Handle<String> capture_value;
1028 ASSIGN_RETURN_ON_EXCEPTION(isolate_, capture_value,
1029 GetCapture(capture_index, &capture_exists),
1030 String);
1031
1032 if (!capture_exists) {
1033 *state = UNMATCHED;
1034 return isolate_->factory()->empty_string();
1035 } else {
1036 *state = MATCHED;
1037 return capture_value;
1038 }
1034 } 1039 }
1035 1040
1036 private: 1041 private:
1037 Isolate* isolate_; 1042 Isolate* isolate_;
1038 Handle<String> subject_; 1043 Handle<String> subject_;
1039 Handle<RegExpMatchInfo> match_info_; 1044 Handle<RegExpMatchInfo> match_info_;
1040 1045
1041 bool has_named_captures_; 1046 bool has_named_captures_;
1042 Handle<FixedArray> capture_name_map_; 1047 Handle<FixedArray> capture_name_map_;
1043 }; 1048 };
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 Handle<Object> capture_obj = captures_->at(i); 1084 Handle<Object> capture_obj = captures_->at(i);
1080 if (capture_obj->IsUndefined(isolate_)) { 1085 if (capture_obj->IsUndefined(isolate_)) {
1081 *capture_exists = false; 1086 *capture_exists = false;
1082 return isolate_->factory()->empty_string(); 1087 return isolate_->factory()->empty_string();
1083 } 1088 }
1084 *capture_exists = true; 1089 *capture_exists = true;
1085 return Object::ToString(isolate_, capture_obj); 1090 return Object::ToString(isolate_, capture_obj);
1086 } 1091 }
1087 1092
1088 MaybeHandle<String> GetNamedCapture(Handle<String> name, 1093 MaybeHandle<String> GetNamedCapture(Handle<String> name,
1089 bool* capture_exists) override { 1094 CaptureState* state) override {
1090 DCHECK(has_named_captures_); 1095 DCHECK(has_named_captures_);
1096
1097 Maybe<bool> maybe_capture_exists =
1098 JSReceiver::HasProperty(groups_obj_, name);
1099 if (maybe_capture_exists.IsNothing()) return MaybeHandle<String>();
1100
1101 if (!maybe_capture_exists.FromJust()) {
1102 *state = INVALID;
1103 return name; // Arbitrary string handle.
1104 }
1105
1091 Handle<Object> capture_obj; 1106 Handle<Object> capture_obj;
1092 ASSIGN_RETURN_ON_EXCEPTION(isolate_, capture_obj, 1107 ASSIGN_RETURN_ON_EXCEPTION(isolate_, capture_obj,
1093 Object::GetProperty(groups_obj_, name), String); 1108 Object::GetProperty(groups_obj_, name), String);
1094 if (capture_obj->IsUndefined(isolate_)) { 1109 if (capture_obj->IsUndefined(isolate_)) {
1095 *capture_exists = false; 1110 *state = UNMATCHED;
1096 return name; 1111 return isolate_->factory()->empty_string();
1097 } else { 1112 } else {
1098 *capture_exists = true; 1113 *state = MATCHED;
1099 return Object::ToString(isolate_, capture_obj); 1114 return Object::ToString(isolate_, capture_obj);
1100 } 1115 }
1101 } 1116 }
1102 1117
1103 private: 1118 private:
1104 Isolate* isolate_; 1119 Isolate* isolate_;
1105 Handle<String> subject_; 1120 Handle<String> subject_;
1106 Handle<String> match_; 1121 Handle<String> match_;
1107 const int match_position_; 1122 const int match_position_;
1108 ZoneVector<Handle<Object>>* captures_; 1123 ZoneVector<Handle<Object>>* captures_;
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after
1885 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1900 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1886 isolate, replacement_obj, 1901 isolate, replacement_obj,
1887 Execution::Call(isolate, replace_obj, factory->undefined_value(), 1902 Execution::Call(isolate, replace_obj, factory->undefined_value(),
1888 argc, argv.start())); 1903 argc, argv.start()));
1889 1904
1890 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1905 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1891 isolate, replacement, Object::ToString(isolate, replacement_obj)); 1906 isolate, replacement, Object::ToString(isolate, replacement_obj));
1892 } else { 1907 } else {
1893 DCHECK(!functional_replace); 1908 DCHECK(!functional_replace);
1894 if (!groups_obj->IsUndefined(isolate)) { 1909 if (!groups_obj->IsUndefined(isolate)) {
1895 // TODO(jgruber): Behavior in this case is not yet specced.
1896 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1910 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1897 isolate, groups_obj, JSReceiver::ToObject(isolate, groups_obj)); 1911 isolate, groups_obj, JSReceiver::ToObject(isolate, groups_obj));
1898 } 1912 }
1899 VectorBackedMatch m(isolate, string, match, position, &captures, 1913 VectorBackedMatch m(isolate, string, match, position, &captures,
1900 groups_obj); 1914 groups_obj);
1901 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1915 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1902 isolate, replacement, String::GetSubstitution(isolate, &m, replace)); 1916 isolate, replacement, String::GetSubstitution(isolate, &m, replace));
1903 } 1917 }
1904 1918
1905 if (position >= next_source_position) { 1919 if (position >= next_source_position) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1942 1956
1943 RUNTIME_FUNCTION(Runtime_IsRegExp) { 1957 RUNTIME_FUNCTION(Runtime_IsRegExp) {
1944 SealHandleScope shs(isolate); 1958 SealHandleScope shs(isolate);
1945 DCHECK_EQ(1, args.length()); 1959 DCHECK_EQ(1, args.length());
1946 CONVERT_ARG_CHECKED(Object, obj, 0); 1960 CONVERT_ARG_CHECKED(Object, obj, 0);
1947 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); 1961 return isolate->heap()->ToBoolean(obj->IsJSRegExp());
1948 } 1962 }
1949 1963
1950 } // namespace internal 1964 } // namespace internal
1951 } // namespace v8 1965 } // namespace v8
OLDNEW
« 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