diff options
Diffstat (limited to 'absl/strings/escaping.cc')
-rw-r--r-- | absl/strings/escaping.cc | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc index 1c0eac42..27d3d98c 100644 --- a/absl/strings/escaping.cc +++ b/absl/strings/escaping.cc @@ -362,7 +362,7 @@ std::string CEscapeInternal(absl::string_view src, bool use_hex, } /* clang-format off */ -constexpr unsigned char c_escaped_len[256] = { +constexpr unsigned char kCEscapedLen[256] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4, // \t, \n, \r 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // ", ' @@ -387,8 +387,23 @@ constexpr unsigned char c_escaped_len[256] = { // that UTF-8 bytes are not handled specially. inline size_t CEscapedLength(absl::string_view src) { size_t escaped_len = 0; - for (char c : src) - escaped_len += c_escaped_len[static_cast<unsigned char>(c)]; + // The maximum value of kCEscapedLen[x] is 4, so we can escape any string of + // length size_t_max/4 without checking for overflow. + size_t unchecked_limit = + std::min<size_t>(src.size(), std::numeric_limits<size_t>::max() / 4); + size_t i = 0; + while (i < unchecked_limit) { + // Common case: No need to check for overflow. + escaped_len += kCEscapedLen[static_cast<unsigned char>(src[i++])]; + } + while (i < src.size()) { + // Beyond unchecked_limit we need to check for overflow before adding. + size_t char_len = kCEscapedLen[static_cast<unsigned char>(src[i++])]; + ABSL_INTERNAL_CHECK( + escaped_len <= std::numeric_limits<size_t>::max() - char_len, + "escaped_len overflow"); + escaped_len += char_len; + } return escaped_len; } @@ -400,12 +415,15 @@ void CEscapeAndAppendInternal(absl::string_view src, std::string* dest) { } size_t cur_dest_len = dest->size(); + ABSL_INTERNAL_CHECK( + cur_dest_len <= std::numeric_limits<size_t>::max() - escaped_len, + "std::string size overflow"); strings_internal::STLStringResizeUninitialized(dest, cur_dest_len + escaped_len); char* append_ptr = &(*dest)[cur_dest_len]; for (char c : src) { - size_t char_len = c_escaped_len[static_cast<unsigned char>(c)]; + size_t char_len = kCEscapedLen[static_cast<unsigned char>(c)]; if (char_len == 1) { *append_ptr++ = c; } else if (char_len == 2) { |