-Wstringop-overflow warning in std::string

Jonathan Wakely jwakely@redhat.com
Thu Feb 27 21:07:00 GMT 2020


Compiling libstd++-v3/testsuite/21_strings/basic_string/cons/char/1.cc
with

   -O2 -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_ASSERTIONS

I see the following warning:

In file included from /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/string:40,
                  from /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/stdexcept:39,
                  from /home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/1.cc:23:
In static member function 'static std::char_traits<char>::char_type* std::char_traits<char>::copy(std::char_traits<char>::char_type*, const char_type*, std::size_t)',
     inlined from 'static void std::basic_string<_CharT, _Traits, _Alloc>::_M_copy(_CharT*, const _CharT*, std::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:3429,
     inlined from 'static void std::basic_string<_CharT, _Traits, _Alloc>::_M_copy(_CharT*, const _CharT*, std::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:3424,
     inlined from 'static void std::basic_string<_CharT, _Traits, _Alloc>::_S_copy_chars(_CharT*, const _CharT*, const _CharT*) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:3476,
     inlined from 'static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct(_InIterator, _InIterator, const _Alloc&, std::forward_iterator_tag) [with _FwdIterator = const char*; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:582,
     inlined from 'static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct(_InIterator, _InIterator, const _Alloc&, std::forward_iterator_tag) [with _FwdIterator = const char*; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:565,
     inlined from 'static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct_aux(_InIterator, _InIterator, const _Alloc&, std::__false_type) [with _InIterator = const char*; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:5121,
     inlined from 'static _CharT* std::basic_string<_CharT, _Traits, _Alloc>::_S_construct(_InIterator, _InIterator, const _Alloc&) [with _InIterator = const char*; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:5142,
     inlined from 'std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, std::basic_string<_CharT, _Traits, _Alloc>::size_type, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:659,
     inlined from 'void test01()' at /home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/1.cc:86:
/home/jwakely/src/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_traits.h:365: warning: 'void* __builtin_memcpy(void*, const void*, long unsigned int)' specified bound 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]

This warning is right, the length passed to the string constructor (on
line 86) is SIZE_MAX, which is clearly a bug. But in practice the
memcpy will never be reached because we check the length and throw an
exception (which is what the testcase is checking for).

Should I just add -Wno-stringop-overflow to the testcase, or would it
be worth doing something like this to inform the compiler?

--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -3423,6 +3423,8 @@ _GLIBCXX_END_NAMESPACE_CXX11
        static void
        _M_copy(_CharT* __d, const _CharT* __s, size_type __n) _GLIBCXX_NOEXCEPT
        {
+       if (__n > _Rep::_S_max_size)
+         __builtin_unreachable();
         if (__n == 1)
           traits_type::assign(*__d, *__s);
         else





More information about the Libstdc++ mailing list