You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[libcxx] Fix basic_string<large value type> buffer replacement
`basic_string` stores a union `__rep` holding one of two structure
types, one (`__long`) with a pointer to an allocated buffer, and
one (`__short`) with a built-in buffer of at least 2 characters (or
however many more will fit). If you make a `basic_string` with an
oversized value type, then the two members of this union are not the
same size, and in particular their `__is_long_` flags (stored at the
end in `_LIBCPP_ABI_ALTERNATE_STRING_LAYOUT` mode) don't alias each
other.
Therefore, when the union is constructed from a `__long`, the
`__is_long_` flag in the `__short` union member is not initialized at
all. Unfortunately, that is where the `__is_long()` method looks.
Commit 28d3194 recently had the side effect that if `__short`
is longer than `__long`, the memory after the `__long` is now
uninitialized rather than zeroed, which can lead to crashes due to
having what looks like a short string with an out-of-range length.
However, even before that commit, the code was still not updating the
string correctly: it would instead have created a short string with
_zero_ length, which is less crash-prone but still not the right
value.
The test `string.modifiers/string_append/push_back.pass.cpp` was
testing this case by calling `push_back` three times on a
`basic_string` with oversized value type, but without checking
anything about the value of the resulting string. Adding some
assertions that the string has the right length at every step would
have caught this bug (both before and after the recent commit).
0 commit comments