@@ -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