This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4630. Off-by-one error in string.replace length_error condition

Section: 27.4.3.7.6 [string.replace] Status: New Submitter: Hubert Tong Opened: 2026-10-26 Last modified: 2026-10-26

Priority: Not Prioritized

View all other issues in [string.replace].

View all issues with New status.

Discussion:

27.4.3.7.6 [string.replace]#8 and 27.4.3.7.6 [string.replace]#12 both specify that size() - xlen >= max_size() - n2 throws length_error. For example, a no-op replace operation on a string whose size() is already max_size() is specified to throw. Neither libstdc++ nor libc++ throws for such a case, and the requirement is suspect.

Code (making use of tiny_size_allocator from the libc++ test support headers); (Compiler Explorer):


#include <assert.h>
#include <string>

template <std::size_t MaxSize, class T> struct tiny_size_allocator {
  using value_type = T;
  using size_type = unsigned;

  template <class U> struct rebind {
    using other = tiny_size_allocator<MaxSize, U>;
  };

  tiny_size_allocator() = default;

  template <class U> tiny_size_allocator(tiny_size_allocator<MaxSize, U>) {}

  T *allocate(std::size_t n) {
    assert(n <= MaxSize);
    return std::allocator<T>().allocate(n);
  }

  void deallocate(T *ptr, std::size_t n) {
    std::allocator<T>().deallocate(ptr, n);
  }

  size_type max_size() const { return MaxSize; }

  friend bool operator==(tiny_size_allocator, tiny_size_allocator) {
    return true;
  }
};

int main() {
  using string_type = std::basic_string<char, std::char_traits<char>,
                                        tiny_size_allocator<17, char>>;
  string_type s;
  s.resize(s.max_size(), 'a');
  assert(s.size() == s.max_size());
  s.replace(0, 0, "", 0);  // specified to throw length_error
}

Proposed resolution: