Martin Sebor wrote: > >Travis Vitek wrote: >> >> If that is the case, then why would we possibly need this >> same code in any of the other methods that are used to extend >> the original string? > >I don't think we do, really. I suspect the main reason why the >code is in all other (out-of-line) modifiers is so we can throw >the exception from function that is called directly by program >rather than from the one that happens to be called from it to >do the real work (all roads lead to replace()). >
The problem I see is this... // if you do this calculation without checking for overflow // you may be surprised when __size becomes smaller than // capacity. [240 + 20 = 6] // const size_type __size = size () + __n; // if we get here and capacity () is 240, but __size is 6 // replace() won't be called. if ( capacity () <= __size || size_type (1) < size_type (_C_pref ()->_C_get_ref ())) return replace (size (), size_type (), __s, __n); // and we will copy past the end of _C_data traits_type::copy (_C_data + size (), __s, __n); // then throw a null terminator down traits_type::assign (_C_data [__size], value_type ()); // and record the wrong size _C_pref ()->_C_size._C_size = __size; With the default std::string/wstring, there isn't really a problem because the allocator fails before size_type will overflow, but that doesn't mean it isn't a problem. Travis > >I think the test case has some problems but I just saw your >update so I'll follow up on it there. > >Martin >