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
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 2e64f1a..9dde5e5 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -182,6 +182,7 @@
         ":resize_and_overwrite",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:throw_delegate",
     ],
 )
 
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index 24408ca..2b97fb5 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -183,6 +183,7 @@
     absl::config
     absl::core_headers
     absl::strings_resize_and_overwrite
+    absl::throw_delegate
 )
 
 absl_cc_test(
diff --git a/absl/strings/internal/append_and_overwrite.h b/absl/strings/internal/append_and_overwrite.h
index 0bb1215..9dec73b 100644
--- a/absl/strings/internal/append_and_overwrite.h
+++ b/absl/strings/internal/append_and_overwrite.h
@@ -16,6 +16,7 @@
 #define ABSL_STRINGS_INTERNAL_APPEND_AND_OVERWRITE_H_
 
 #include "absl/base/config.h"
+#include "absl/base/internal/throw_delegate.h"
 #include "absl/base/macros.h"
 #include "absl/base/optimization.h"
 #include "absl/strings/resize_and_overwrite.h"
@@ -44,17 +45,24 @@
 template <typename T, typename Op>
 void StringAppendAndOverwrite(T& str, typename T::size_type append_n,
                               Op append_op) {
-  ABSL_HARDENING_ASSERT(str.size() <= str.max_size() - append_n);
+  if (ABSL_PREDICT_FALSE(append_n > str.max_size() - str.size())) {
+    absl::base_internal::ThrowStdLengthError(
+        "absl::strings_internal::StringAppendAndOverwrite");
+  }
+
   auto old_size = str.size();
   auto resize = old_size + append_n;
 
-  // Make sure to always grow by at least a factor of 2x.
   if (resize > str.capacity()) {
-    if (ABSL_PREDICT_FALSE(str.capacity() > str.max_size() / 2)) {
+    // Make sure to always grow by at least a factor of 2x.
+    const auto min_growth = str.capacity();
+    if (ABSL_PREDICT_FALSE(str.capacity() > str.max_size() - min_growth)) {
       resize = str.max_size();
-    } else if (resize < str.capacity() * 2) {
-      resize = str.capacity() * 2;
+    } else if (resize < str.capacity() + min_growth) {
+      resize = str.capacity() + min_growth;
     }
+  } else {
+    resize = str.capacity();
   }
 
   // Avoid calling StringResizeAndOverwrite() here since it does an MSAN
diff --git a/absl/strings/resize_and_overwrite.h b/absl/strings/resize_and_overwrite.h
index 169c685..04c12d2 100644
--- a/absl/strings/resize_and_overwrite.h
+++ b/absl/strings/resize_and_overwrite.h
@@ -159,7 +159,7 @@
   } else if constexpr (strings_internal::has_Resize_and_overwrite<T>::value) {
     str._Resize_and_overwrite(n, std::move(op));
   } else {
-    strings_internal::StringResizeAndOverwriteFallback(str, n, op);
+    strings_internal::StringResizeAndOverwriteFallback(str, n, std::move(op));
   }
 #endif
 }