@@ -190,10 +190,14 @@ bool IsLineTerminator(int c){
190190// WriteEscapedRegExpSource into a single function to deduplicate dispatch logic
191191// and move related code closer to each other.
192192template <typename Char>
193- int CountAdditionalEscapeChars(DirectHandle<String> source,
194- bool* needs_escapes_out){
193+ uint32_t CountAdditionalEscapeChars(DirectHandle<String> source,
194+ bool* needs_escapes_out){
195195 DisallowGarbageCollection no_gc;
196- int escapes = 0;
196+ uint32_t escapes = 0;
197+ // The maximum growth-factor is 5 (for \u2028 and \u2029). Make sure that we
198+ // won't overflow |escapes| given the current constraints on string length.
199+ static_assert(uint64_t{String::kMaxLength} * 5 <
200+ std::numeric_limits<decltype(escapes)>::max());
197201 bool needs_escapes = false;
198202 bool in_character_class = false;
199203 base::Vector<const Char> src = source->GetCharVector<Char>(no_gc);
@@ -232,14 +236,14 @@ int CountAdditionalEscapeChars(DirectHandle<String> source,
232236 }
233237 }
234238 DCHECK(!in_character_class);
235- DCHECK_GE(escapes, 0);
236239 DCHECK_IMPLIES(escapes != 0, needs_escapes);
237240 *needs_escapes_out = needs_escapes;
238241 return escapes;
239242}
240243
241244template <typename Char>
242- void WriteStringToCharVector(base::Vector<Char> v, int* d, const char* string){
245+ void WriteStringToCharVector(base::Vector<Char> v, uint32_t* d,
246+ const char* string){
243247 int s = 0;
244248 while (string[s] != '\0') v[(*d)++] = string[s++];
245249}
@@ -250,21 +254,21 @@ DirectHandle<StringType> WriteEscapedRegExpSource(
250254 DisallowGarbageCollection no_gc;
251255 base::Vector<const Char> src = source->GetCharVector<Char>(no_gc);
252256 base::Vector<Char> dst(result->GetChars(no_gc), result->length());
253- int s = 0;
254- int d = 0;
257+ uint32_t s = 0;
258+ uint32_t d = 0;
255259 bool in_character_class = false;
256- while (s < src.length ()){
260+ while (s < src.size ()){
257261 const Char c = src[s];
258262 if (c == '\\'){
259- if (s + 1 < src.length () && IsLineTerminator(src[s + 1])){
263+ if (s + 1 < src.size () && IsLineTerminator(src[s + 1])){
260264 // This '\' is ignored since the next character itself will be escaped.
261265 s++;
262266 continue;
263267 } else{
264268 // Escape. Copy this and next character.
265269 dst[d++] = src[s++];
266270 }
267- if (s == src.length ()) break;
271+ if (s == src.size ()) break;
268272 } else if (c == '/' && !in_character_class){
269273 // Not escaped forward-slash needs escape.
270274 dst[d++] = '\\'
@@ -304,11 +308,13 @@ MaybeDirectHandle<String> EscapeRegExpSource(Isolate* isolate,
304308 if (source->length() == 0) return isolate->factory()->query_colon_string();
305309 bool one_byte = String::IsOneByteRepresentationUnderneath(*source);
306310 bool needs_escapes = false;
307- int additional_escape_chars =
311+ uint32_t additional_escape_chars =
308312 one_byte ? CountAdditionalEscapeChars<uint8_t>(source, &needs_escapes)
309313 : CountAdditionalEscapeChars<base::uc16>(source, &needs_escapes);
310314 if (!needs_escapes) return source;
311- int length = source->length() + additional_escape_chars;
315+ DCHECK_LE(static_cast<uint64_t>(source->length()) + additional_escape_chars,
316+ std::numeric_limits<uint32_t>::max());
317+ uint32_t length = source->length() + additional_escape_chars;
312318 if (one_byte){
313319 DirectHandle<SeqOneByteString> result;
314320 ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
0 commit comments