https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89446

            Bug ID: 89446
           Summary: [7/8 Regression] __builtin_constant_p expression
                    crashes in char_traits::compare
           Product: gcc
           Version: 8.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

#include <string_view>

int main()
{
  std::string_view s1, s2;
  return s1 == s2;
}

This crashes when compiled with -std=c++17 -O1 -fnon-call-exceptions

Program received signal SIGSEGV, Segmentation fault.
main () at /usr/include/c++/8/bits/char_traits.h:303
303             if (__builtin_constant_p(__n)
#0  main () at /usr/include/c++/8/bits/char_traits.h:303

I think the fix is:

--- a/libstdc++-v3/include/bits/char_traits.h
+++ b/libstdc++-v3/include/bits/char_traits.h
@@ -248,7 +248,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __constant_char_array_p(const _CharT* __a, size_t __n)
     {
       size_t __i = 0;
-      while (__builtin_constant_p(__a[__i]) && __i < __n)
+      while (__i < __n && __builtin_constant_p(__a[__i]) && __i < __n)
        __i++;
       return __i == __n;
     }

But we can also avoid those checks entirely for empty strings:


@@ -301,14 +301,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static _GLIBCXX17_CONSTEXPR int
       compare(const char_type* __s1, const char_type* __s2, size_t __n)
       {
+       if (__n == 0)
+         return 0;
 #if __cplusplus > 201402
        if (__builtin_constant_p(__n)
            && __constant_char_array_p(__s1, __n)
            && __constant_char_array_p(__s2, __n))
          return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
 #endif
-       if (__n == 0)
-         return 0;
        return __builtin_memcmp(__s1, __s2, __n);
       }

(and similarly in char_traits<char>::find and char_traits<wchar_t>).


It doesn't currently fail on trunk, because we use
__builtin_is_constant_evaluated now instead of the __builtin_constant_p checks,
but the bug is still present.

Reply via email to