diff options
Diffstat (limited to 'absl')
-rw-r--r-- | absl/strings/internal/escaping.cc | 7 | ||||
-rw-r--r-- | absl/strings/internal/str_join_internal.h | 12 | ||||
-rw-r--r-- | absl/strings/str_cat.cc | 45 | ||||
-rw-r--r-- | absl/strings/substitute.cc | 4 |
4 files changed, 56 insertions, 12 deletions
diff --git a/absl/strings/internal/escaping.cc b/absl/strings/internal/escaping.cc index 56a4cbed..d2abe669 100644 --- a/absl/strings/internal/escaping.cc +++ b/absl/strings/internal/escaping.cc @@ -14,6 +14,8 @@ #include "absl/strings/internal/escaping.h" +#include <limits> + #include "absl/base/internal/endian.h" #include "absl/base/internal/raw_logging.h" @@ -31,12 +33,14 @@ ABSL_CONST_INIT const char kBase64Chars[] = ABSL_CONST_INIT const char kWebSafeBase64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) { // Base64 encodes three bytes of input at a time. If the input is not // divisible by three, we pad as appropriate. // // Base64 encodes each three bytes of input into four bytes of output. + constexpr size_t kMaxSize = (std::numeric_limits<size_t>::max() - 1) / 4 * 3; + ABSL_INTERNAL_CHECK(input_len <= kMaxSize, + "CalculateBase64EscapedLenInternal() overflow"); size_t len = (input_len / 3) * 4; // Since all base 64 input is an integral number of octets, only the following @@ -66,7 +70,6 @@ size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) { } } - assert(len >= input_len); // make sure we didn't overflow return len; } diff --git a/absl/strings/internal/str_join_internal.h b/absl/strings/internal/str_join_internal.h index d97d5033..96d41b68 100644 --- a/absl/strings/internal/str_join_internal.h +++ b/absl/strings/internal/str_join_internal.h @@ -31,13 +31,16 @@ #ifndef ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_ #define ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_ +#include <cstdint> #include <cstring> #include <iterator> +#include <limits> #include <memory> #include <string> #include <type_traits> #include <utility> +#include "absl/base/internal/raw_logging.h" #include "absl/strings/internal/ostringstream.h" #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/str_cat.h" @@ -230,14 +233,19 @@ std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s, if (start != end) { // Sums size auto&& start_value = *start; - size_t result_size = start_value.size(); + // Use uint64_t to prevent size_t overflow. We assume it is not possible for + // in memory strings to overflow a uint64_t. + uint64_t result_size = start_value.size(); for (Iterator it = start; ++it != end;) { result_size += s.size(); result_size += (*it).size(); } if (result_size > 0) { - STLStringResizeUninitialized(&result, result_size); + constexpr uint64_t kMaxSize = + uint64_t{(std::numeric_limits<size_t>::max)()}; + ABSL_INTERNAL_CHECK(result_size <= kMaxSize, "size_t overflow"); + STLStringResizeUninitialized(&result, static_cast<size_t>(result_size)); // Joins strings char* result_buf = &*result.begin(); diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc index 098ab183..b637b551 100644 --- a/absl/strings/str_cat.cc +++ b/absl/strings/str_cat.cc @@ -20,10 +20,12 @@ #include <cstdint> #include <cstring> #include <initializer_list> +#include <limits> #include <string> #include <type_traits> #include "absl/base/config.h" +#include "absl/base/internal/raw_logging.h" #include "absl/base/nullability.h" #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/numbers.h" @@ -32,7 +34,6 @@ namespace absl { ABSL_NAMESPACE_BEGIN - // ---------------------------------------------------------------------- // StrCat() // This merges the given strings or integers, with no delimiter. This @@ -57,8 +58,14 @@ absl::Nonnull<char*> Append(absl::Nonnull<char*> out, const AlphaNum& x) { std::string StrCat(const AlphaNum& a, const AlphaNum& b) { std::string result; - absl::strings_internal::STLStringResizeUninitialized(&result, - a.size() + b.size()); + // Use uint64_t to prevent size_t overflow. We assume it is not possible for + // in memory strings to overflow a uint64_t. + constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()}; + const uint64_t result_size = + static_cast<uint64_t>(a.size()) + static_cast<uint64_t>(b.size()); + ABSL_INTERNAL_CHECK(result_size <= kMaxSize, "size_t overflow"); + absl::strings_internal::STLStringResizeUninitialized( + &result, static_cast<size_t>(result_size)); char* const begin = &result[0]; char* out = begin; out = Append(out, a); @@ -69,8 +76,15 @@ std::string StrCat(const AlphaNum& a, const AlphaNum& b) { std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) { std::string result; + // Use uint64_t to prevent size_t overflow. We assume it is not possible for + // in memory strings to overflow a uint64_t. + constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()}; + const uint64_t result_size = static_cast<uint64_t>(a.size()) + + static_cast<uint64_t>(b.size()) + + static_cast<uint64_t>(c.size()); + ABSL_INTERNAL_CHECK(result_size <= kMaxSize, "size_t overflow"); strings_internal::STLStringResizeUninitialized( - &result, a.size() + b.size() + c.size()); + &result, static_cast<size_t>(result_size)); char* const begin = &result[0]; char* out = begin; out = Append(out, a); @@ -83,8 +97,16 @@ std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) { std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d) { std::string result; + // Use uint64_t to prevent size_t overflow. We assume it is not possible for + // in memory strings to overflow a uint64_t. + constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()}; + const uint64_t result_size = static_cast<uint64_t>(a.size()) + + static_cast<uint64_t>(b.size()) + + static_cast<uint64_t>(c.size()) + + static_cast<uint64_t>(d.size()); + ABSL_INTERNAL_CHECK(result_size <= kMaxSize, "size_t overflow"); strings_internal::STLStringResizeUninitialized( - &result, a.size() + b.size() + c.size() + d.size()); + &result, static_cast<size_t>(result_size)); char* const begin = &result[0]; char* out = begin; out = Append(out, a); @@ -224,9 +246,16 @@ void SingleArgStrAppend(std::string& str, unsigned long long x) { std::string CatPieces(std::initializer_list<absl::string_view> pieces) { std::string result; - size_t total_size = 0; - for (absl::string_view piece : pieces) total_size += piece.size(); - strings_internal::STLStringResizeUninitialized(&result, total_size); + // Use uint64_t to prevent size_t overflow. We assume it is not possible for + // in memory strings to overflow a uint64_t. + constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()}; + uint64_t total_size = 0; + for (absl::string_view piece : pieces) { + total_size += piece.size(); + } + ABSL_INTERNAL_CHECK(total_size <= kMaxSize, "size_t overflow"); + strings_internal::STLStringResizeUninitialized( + &result, static_cast<size_t>(total_size)); char* const begin = &result[0]; char* out = begin; diff --git a/absl/strings/substitute.cc b/absl/strings/substitute.cc index dd32c75f..a71f565a 100644 --- a/absl/strings/substitute.cc +++ b/absl/strings/substitute.cc @@ -18,6 +18,7 @@ #include <cassert> #include <cstddef> #include <cstdint> +#include <limits> #include <string> #include "absl/base/config.h" @@ -84,6 +85,9 @@ void SubstituteAndAppendArray( // Build the string. size_t original_size = output->size(); + ABSL_INTERNAL_CHECK( + size <= std::numeric_limits<size_t>::max() - original_size, + "size_t overflow"); strings_internal::STLStringResizeUninitializedAmortized(output, original_size + size); char* target = &(*output)[original_size]; |