https://gcc.gnu.org/g:8ba83d3dab23d6b653988b4fd81657c043f0e9fa
commit r17-5130-g8ba83d3dab23d6b653988b4fd81657c043f0e9fa Author: Nathan Myers <[email protected]> Date: Thu Oct 8 19:31:27 2026 -0400 libstdc++: restore old _M_create behavior [PR127228] acfdad706d8 added a basic_string member _M_create_plus to use when allocating string storage, but retained the old _M_create symbol so that object files built against older releases would still find it. However, code built into some old object files relies on _M_create to allocate no more bytes than requested when the old capacity is zero, something it no longer does. This patch restores _M_create's exact previous behavior, to rescue those old object files. libstdc++-v3/ChangeLog: PR libstdc++/127228 * include/bits/basic_string.tcc (_M_create): Restore old version. * testsuite/21_strings/basic_string/127228.cc: New test. Diff: --- libstdc++-v3/include/bits/basic_string.tcc | 12 ++++++++--- .../testsuite/21_strings/basic_string/127228.cc | 25 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index 64c99fbb9d64..de82e9978888 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -171,9 +171,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_string<_CharT, _Traits, _Alloc>:: _M_create(size_type& __capacity, size_type __old_capacity) { - _Alloc_result __r = _M_create_plus(__capacity, __old_capacity); - __capacity = __r.__count - 1; // Leave room for NUL. - return __r.__ptr; + if (__capacity > max_size()) + std::__throw_length_error(__N("basic_string::_M_create")); + if (__capacity > __old_capacity && __capacity < 2 * __old_capacity) + { + __capacity = 2 * __old_capacity; + if (__capacity > max_size()) + __capacity = max_size(); + } + return _S_allocate(_M_get_allocator(), __capacity + 1); } // NB: This is the special case for Input Iterators, used in diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/127228.cc b/libstdc++-v3/testsuite/21_strings/basic_string/127228.cc new file mode 100644 index 000000000000..a0517c320f18 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/127228.cc @@ -0,0 +1,25 @@ +// { dg-do run { target c++23 } } +// { dg-options "-fno-access-control -fno-inline -fno-ipa-sra -fno-ipa-modref -fno-ipa-cp -fno-ipa-icf" } + +// libstdc++/127228 +// Object files built against older libstdc++ still call _M_create +// and rely on it to allocate and report allocating no more storage +// than was asked for when the old capacity is 0. + +#include <string> +#include <testsuite_hooks.h> + +int main() +{ + std::string s; + { + std::string::size_type new_cap = 25, old_cap = 0; + (void) s._M_create(new_cap, old_cap); + VERIFY(new_cap == 25); + } + { + std::string::size_type new_cap = 2, old_cap = 0; + (void) s._M_create(new_cap, old_cap); + VERIFY(new_cap == 2); + } +}
