Clang's "unsigned integer overflow" sanitizer can't tell the difference
between expected unsigned wraparound and a bug, and its developers tell
users to report bugs against libstdc++.

This disables the sanitizer where we are intentionally relying on
wraparound working as defined by the standard.

libstdc++-v3/ChangeLog:

        PR libstdc++/91547
        PR libstdc++/97844
        * include/bits/c++config (_GLIBCXX_NO_UNSIGNED_OVERFLOW): Define
        new macro for Clang's no_sanitize("unsigned-integer-overflow")
        attribute.
        * include/bits/basic_string.h (basic_string::_S_compare): Add
        _GLIBCXX_NO_UNSIGNED_OVERFLOW.
        * include/bits/basic_string.tcc (basic_string::find_last_of)
        (basic_string::find_last_not_of): Likewise.
        * include/bits/string_view.tcc
        (basic_string_view::find_last_not_of): Likewise.
        * include/std/string_view (basic_string_view::_S_compare):
        Likewise.

Should we make this change? It won't stop bogus bug reports unless we
also do it on the branches, or wait until nobody is using older
libstdc++ headers with recent Clang releases. But it might help
eventually.



commit 3bceeb9366ea416ca3dbe0cd965151a7bdc7cfcf
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Mon Nov 16 13:09:37 2020

    libstdc++ Disable bogus -fsanitize=integer errors from Clang
    
    Clang's "unsigned integer overflow" sanitizer can't tell the difference
    between expected unsigned wraparound and a bug, and its developers tell
    users to report bugs against libstdc++.
    
    This disables the sanitizer where we are intentionally relying on
    wraparound working as defined by the standard.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/91547
            PR libstdc++/97844
            * include/bits/c++config (_GLIBCXX_NO_UNSIGNED_OVERFLOW): Define
            new macro for Clang's no_sanitize("unsigned-integer-overflow")
            attribute.
            * include/bits/basic_string.h (basic_string::_S_compare): Add
            _GLIBCXX_NO_UNSIGNED_OVERFLOW.
            * include/bits/basic_string.tcc (basic_string::find_last_of)
            (basic_string::find_last_not_of): Likewise.
            * include/bits/string_view.tcc
            (basic_string_view::find_last_not_of): Likewise.
            * include/std/string_view (basic_string_view::_S_compare):
            Likewise.

diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 372302ba6a18..1c805e5ad8ae 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -397,6 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       _GLIBCXX_NOEXCEPT
       { _S_copy(__p, __k1, __k2 - __k1); }
 
+      _GLIBCXX_NO_UNSIGNED_OVERFLOW
       static int
       _S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPT
       {
@@ -3482,6 +3483,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
       _GLIBCXX_NOEXCEPT
       { _M_copy(__p, __k1, __k2 - __k1); }
 
+      _GLIBCXX_NO_UNSIGNED_OVERFLOW
       static int
       _S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPT
       {
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index 6c7896651609..d88b9692f9a0 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -1307,6 +1307,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
+    _GLIBCXX_NO_UNSIGNED_OVERFLOW
     typename basic_string<_CharT, _Traits, _Alloc>::size_type
     basic_string<_CharT, _Traits, _Alloc>::
     find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
@@ -1353,6 +1354,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
+    _GLIBCXX_NO_UNSIGNED_OVERFLOW
     typename basic_string<_CharT, _Traits, _Alloc>::size_type
     basic_string<_CharT, _Traits, _Alloc>::
     find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
@@ -1375,6 +1377,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
+    _GLIBCXX_NO_UNSIGNED_OVERFLOW
     typename basic_string<_CharT, _Traits, _Alloc>::size_type
     basic_string<_CharT, _Traits, _Alloc>::
     find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 2e6c880ad95a..95fb934564e3 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -702,6 +702,13 @@ namespace std
     { __glibcxx_assert_2(_Condition); }   \
   } while (false)
 
+#if __has_attribute(__no_sanitize__) && defined __clang__
+// Suppress UBsan errors about unsigned wraparound.
+# define _GLIBCXX_NO_UNSIGNED_OVERFLOW \
+      __attribute__((__no_sanitize__("unsigned-integer-overflow")))
+#else
+# define _GLIBCXX_NO_UNSIGNED_OVERFLOW
+#endif
 
 // PSTL configuration
 
diff --git a/libstdc++-v3/include/bits/string_view.tcc b/libstdc++-v3/include/bits/string_view.tcc
index 88d9371f1906..30f35e446a07 100644
--- a/libstdc++-v3/include/bits/string_view.tcc
+++ b/libstdc++-v3/include/bits/string_view.tcc
@@ -180,6 +180,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
+    _GLIBCXX_NO_UNSIGNED_OVERFLOW
     constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_last_not_of(const _CharT* __str, size_type __pos,
@@ -202,6 +203,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _CharT, typename _Traits>
+    _GLIBCXX_NO_UNSIGNED_OVERFLOW
     constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_last_not_of(_CharT __c, size_type __pos) const noexcept
diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view
index 656d06bf90e9..5c939a388a7f 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -456,6 +456,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     private:
 
+      _GLIBCXX_NO_UNSIGNED_OVERFLOW
       static constexpr int
       _S_compare(size_type __n1, size_type __n2) noexcept
       {

Reply via email to