Skip to content

Commit f43bcc0

Browse files
derekmaurocopybara-github
authored andcommitted
Fixes for String{Resize|Append}AndOverwrite
- StringAppendAndOverwrite() should always call StringResizeAndOverwrite() with at least capacity() in case the standard library decides to shrink the buffer (Fixes #1965) - Small refactor to make the minimum growth an addition for clarity and to make it easier to test 1.5x growth in the future - Turn an ABSL_HARDENING_ASSERT into a ThrowStdLengthError - Add a missing std::move PiperOrigin-RevId: 826107106 Change-Id: I73ee3e98daa10161aa9023b2a879f6178ebedbcf
1 parent 01a4ea7 commit f43bcc0

File tree

4 files changed

+16
-6
lines changed

4 files changed

+16
-6
lines changed

absl/strings/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ cc_library(
182182
":resize_and_overwrite",
183183
"//absl/base:config",
184184
"//absl/base:core_headers",
185+
"//absl/base:throw_delegate",
185186
],
186187
)
187188

absl/strings/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ absl_cc_library(
183183
absl::config
184184
absl::core_headers
185185
absl::strings_resize_and_overwrite
186+
absl::throw_delegate
186187
)
187188

188189
absl_cc_test(

absl/strings/internal/append_and_overwrite.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define ABSL_STRINGS_INTERNAL_APPEND_AND_OVERWRITE_H_
1717

1818
#include "absl/base/config.h"
19+
#include "absl/base/internal/throw_delegate.h"
1920
#include "absl/base/macros.h"
2021
#include "absl/base/optimization.h"
2122
#include "absl/strings/resize_and_overwrite.h"
@@ -44,17 +45,24 @@ namespace strings_internal {
4445
template <typename T, typename Op>
4546
void StringAppendAndOverwrite(T& str, typename T::size_type append_n,
4647
Op append_op) {
47-
ABSL_HARDENING_ASSERT(str.size() <= str.max_size() - append_n);
48+
if (ABSL_PREDICT_FALSE(append_n > str.max_size() - str.size())) {
49+
absl::base_internal::ThrowStdLengthError(
50+
"absl::strings_internal::StringAppendAndOverwrite");
51+
}
52+
4853
auto old_size = str.size();
4954
auto resize = old_size + append_n;
5055

51-
// Make sure to always grow by at least a factor of 2x.
5256
if (resize > str.capacity()) {
53-
if (ABSL_PREDICT_FALSE(str.capacity() > str.max_size() / 2)) {
57+
// Make sure to always grow by at least a factor of 2x.
58+
const auto min_growth = str.capacity();
59+
if (ABSL_PREDICT_FALSE(str.capacity() > str.max_size() - min_growth)) {
5460
resize = str.max_size();
55-
} else if (resize < str.capacity() * 2) {
56-
resize = str.capacity() * 2;
61+
} else if (resize < str.capacity() + min_growth) {
62+
resize = str.capacity() + min_growth;
5763
}
64+
} else {
65+
resize = str.capacity();
5866
}
5967

6068
// Avoid calling StringResizeAndOverwrite() here since it does an MSAN

absl/strings/resize_and_overwrite.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ void StringResizeAndOverwriteImpl(T& str, typename T::size_type n, Op op) {
159159
} else if constexpr (strings_internal::has_Resize_and_overwrite<T>::value) {
160160
str._Resize_and_overwrite(n, std::move(op));
161161
} else {
162-
strings_internal::StringResizeAndOverwriteFallback(str, n, op);
162+
strings_internal::StringResizeAndOverwriteFallback(str, n, std::move(op));
163163
}
164164
#endif
165165
}

0 commit comments

Comments
 (0)