[v2,1/1] libstdc++: Set _M_string_length before calling _M_dispose() [PR109703]

Message ID 20230503021713.1146069-2-tchaikov@gmail.com
State Accepted
Headers
Series Set _M_string_length before calling _M_dispose() |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

kefu chai May 3, 2023, 2:17 a.m. UTC
  This patch always sets _M_string_length in the constructor specialized
for range of input_iterator, for the cases like istringstream.

We copy from source range to the local buffer, and then reallocate to
a larger one if necessary. When disposing the old buffer, the old buffer
could be provisioned by the local buffer or an allocated buffer.
_M_is_local() is used to tell if the buffer is the local one or not. In
addition to comparing the buffer address with the local buffer, this
function also performs the sanity checking if _M_string_length is greater
than _S_local_capacity, if the check fails __builtin_unreachable() is
called. But we failed to set _M_string_length in this constructor is
specialized for std::input_iterator. So, if UBSan is enabled when
compiling the source, there are chances that the uninitialized data in
_M_string_length is greater than _S_local_capacity, and the application
aborts a runtime error or exception emitted by the UBSan.

In this change, to avoid the false alarm, _M_string_length is
initialized to zero before doing anything else, so that _M_is_local()
doesn't see an uninitialized value.

This issue only surfaces when constructing a string with a range of
input_iterator, and the uninitialized _M_string_length is greater than
_S_local_capacity, i.e., 15.

libstdc++-v3/ChangeLog:

        PR libstdc++/109703
        * include/bits/basic_string.h (basic_string(Iter, Iter, Alloc)):
        Initialize _M_string_length.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>
Co-authored-by: Jonathan Wakely <jwakely@redhat.com>
---
 libstdc++-v3/include/bits/basic_string.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
  

Patch

diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 8247ee6bdc6..b16b2898b62 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -760,7 +760,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
 	_GLIBCXX20_CONSTEXPR
         basic_string(_InputIterator __beg, _InputIterator __end,
 		     const _Alloc& __a = _Alloc())
-	: _M_dataplus(_M_local_data(), __a)
+	: _M_dataplus(_M_local_data(), __a), _M_string_length(0)
 	{
 #if __cplusplus >= 201103L
 	  _M_construct(__beg, __end, std::__iterator_category(__beg));