Title
Off-by-one error in string.replace length_error condition
Status
new
Section
[string.replace]
Submitter
Hubert Tong

Created on 2026-10-26.00:00:00 last changed 1 week ago

Messages

Date: 2026-10-26.11:56:08

[string.replace]#8 and [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
}
History
Date User Action Args
2026-10-26 00:00:00admincreate