re PR libstdc++/65049 (Undefined behaviour with std::char_traits<char>)
authorJonathan Wakely <jwakely@redhat.com>
Mon, 24 Aug 2015 13:43:54 +0000 (14:43 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 24 Aug 2015 13:43:54 +0000 (14:43 +0100)
PR libstdc++/65049
* include/bits/char_traits.h (char_traits<char>::compare,
char_traits<char>::find, char_traits<char>::move,
char_traits<char>::copy, char_traits<char>::assign): Check for zero
length.
(char_traits<wchar_t>::compare, char_traits<wchar_t>::find,
char_traits<wchar_t>::move, char_traits<wchar_t>::copy,
char_traits<wchar_t>::assign): Likewise.
(char_traits<char16_t>::move, char_traits<char16_t>::copy): Likewise.
(char_traits<char32_t>::move, char_traits<char32_t>::copy): Likewise.
* include/ext/pod_char_traits.h (char_traits<character<>>::move,
char_traits<character<>>::copy): Likewise.
* testsuite/21_strings/char_traits/requirements/char/65049.cc: New.
* testsuite/21_strings/char_traits/requirements/char16_t/65049.cc:
New.
* testsuite/21_strings/char_traits/requirements/char32_t/65049.cc:
New.
* testsuite/21_strings/char_traits/requirements/wchar_t/65049.cc:
New.

From-SVN: r227127

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/char_traits.h
libstdc++-v3/include/ext/pod_char_traits.h
libstdc++-v3/testsuite/21_strings/char_traits/requirements/char/65049.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/char_traits/requirements/char16_t/65049.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/char_traits/requirements/char32_t/65049.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/char_traits/requirements/wchar_t/65049.cc [new file with mode: 0644]

index 090e8e3373a2aa6abbe5a2adb76d97e2278294c3..f6f68a813016260f16edb3bc3eec1f38eb8f758b 100644 (file)
@@ -1,5 +1,25 @@
 2015-08-24  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/65049
+       * include/bits/char_traits.h (char_traits<char>::compare,
+       char_traits<char>::find, char_traits<char>::move,
+       char_traits<char>::copy, char_traits<char>::assign): Check for zero
+       length.
+       (char_traits<wchar_t>::compare, char_traits<wchar_t>::find,
+       char_traits<wchar_t>::move, char_traits<wchar_t>::copy,
+       char_traits<wchar_t>::assign): Likewise.
+       (char_traits<char16_t>::move, char_traits<char16_t>::copy): Likewise.
+       (char_traits<char32_t>::move, char_traits<char32_t>::copy): Likewise.
+       * include/ext/pod_char_traits.h (char_traits<character<>>::move,
+       char_traits<character<>>::copy): Likewise.
+       * testsuite/21_strings/char_traits/requirements/char/65049.cc: New.
+       * testsuite/21_strings/char_traits/requirements/char16_t/65049.cc:
+       New.
+       * testsuite/21_strings/char_traits/requirements/char32_t/65049.cc:
+       New.
+       * testsuite/21_strings/char_traits/requirements/wchar_t/65049.cc:
+       New.
+
        PR libstdc++/67309
        * include/bits/random.tcc
        (poisson_distribution::param_type::_M_initialize): Use max<double>.
index 369c636d8fd75789cf45eddd268cfacdb9134f12..0d0063bcee6f41d8d31829bc786f029147deaf1d 100644 (file)
@@ -256,7 +256,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       static int
       compare(const char_type* __s1, const char_type* __s2, size_t __n)
-      { return __builtin_memcmp(__s1, __s2, __n); }
+      {
+       if (__n == 0)
+         return 0;
+       return __builtin_memcmp(__s1, __s2, __n);
+      }
 
       static size_t
       length(const char_type* __s)
@@ -264,19 +268,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       static const char_type*
       find(const char_type* __s, size_t __n, const char_type& __a)
-      { return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); }
+      {
+       if (__n == 0)
+         return 0;
+       return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
+      }
 
       static char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
-      { return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); }
+      {
+       if (__n == 0)
+         return __s1;
+       return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
+      }
 
       static char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
-      { return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); }
+      {
+       if (__n == 0)
+         return __s1;
+       return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
+      }
 
       static char_type*
       assign(char_type* __s, size_t __n, char_type __a)
-      { return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); }
+      {
+       if (__n == 0)
+         return __s;
+       return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
+      }
 
       static _GLIBCXX_CONSTEXPR char_type
       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
@@ -327,7 +347,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       static int
       compare(const char_type* __s1, const char_type* __s2, size_t __n)
-      { return wmemcmp(__s1, __s2, __n); }
+      {
+       if (__n == 0)
+         return 0;
+       return wmemcmp(__s1, __s2, __n);
+      }
 
       static size_t
       length(const char_type* __s)
@@ -335,19 +359,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       static const char_type*
       find(const char_type* __s, size_t __n, const char_type& __a)
-      { return wmemchr(__s, __a, __n); }
+      {
+       if (__n == 0)
+         return 0;
+       return wmemchr(__s, __a, __n);
+      }
 
       static char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
-      { return wmemmove(__s1, __s2, __n); }
+      {
+       if (__n == 0)
+         return __s1;
+       return wmemmove(__s1, __s2, __n);
+      }
 
       static char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
-      { return wmemcpy(__s1, __s2, __n); }
+      {
+       if (__n == 0)
+         return __s1;
+       return wmemcpy(__s1, __s2, __n);
+      }
 
       static char_type*
       assign(char_type* __s, size_t __n, char_type __a)
-      { return wmemset(__s, __a, __n); }
+      {
+       if (__n == 0)
+         return __s;
+       return wmemset(__s, __a, __n);
+      }
 
       static _GLIBCXX_CONSTEXPR char_type
       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
@@ -436,6 +476,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
+       if (__n == 0)
+         return __s1;
        return (static_cast<char_type*>
                (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
       }
@@ -443,6 +485,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
+       if (__n == 0)
+         return __s1;
        return (static_cast<char_type*>
                (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
       }
@@ -529,6 +573,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
+       if (__n == 0)
+         return __s1;
        return (static_cast<char_type*>
                (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
       }
@@ -536,6 +582,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       { 
+       if (__n == 0)
+         return __s1;
        return (static_cast<char_type*>
                (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
       }
index c941080f54a40a6906aecbe1afffab37e3dc11ff..38a84c80d5b5ee89089b320d6fa7e195781823ec 100644 (file)
@@ -144,6 +144,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       { 
+       if (__n == 0)
+         return __s1;
        return static_cast<char_type*>
          (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)));
       }
@@ -151,6 +153,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
+       if (__n == 0)
+         return __s1;
        std::copy(__s2, __s2 + __n, __s1);
        return __s1;
       }
diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char/65049.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char/65049.cc
new file mode 100644 (file)
index 0000000..1aa00dd
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+// libstdc++/65049
+
+#include <string>
+#include <testsuite_hooks.h>
+
+using C = char;
+
+void
+test01()
+{
+  const C* p = 0;
+  C* q = 0;
+  auto c = std::char_traits<C>::compare(p, q, 0);
+  VERIFY( c == 0 );
+  auto r = std::char_traits<C>::find(p, 0, '0');
+  VERIFY( r == nullptr );
+  r = std::char_traits<C>::move(q, p, 0);
+  VERIFY( r == q );
+  r = std::char_traits<C>::copy(q, p, 0);
+  VERIFY( r == q );
+  r = std::char_traits<C>::assign(q, 0, '0');
+  VERIFY( r == q );
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char16_t/65049.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char16_t/65049.cc
new file mode 100644 (file)
index 0000000..7af6db3
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+// libstdc++/65049
+
+#include <string>
+#include <testsuite_hooks.h>
+
+using C = char16_t;
+
+void
+test01()
+{
+  const C* p = 0;
+  C* q = 0;
+  auto c = std::char_traits<C>::compare(p, q, 0);
+  VERIFY( c == 0 );
+  auto r = std::char_traits<C>::find(p, 0, '0');
+  VERIFY( r == nullptr );
+  r = std::char_traits<C>::move(q, p, 0);
+  VERIFY( r == q );
+  r = std::char_traits<C>::copy(q, p, 0);
+  VERIFY( r == q );
+  r = std::char_traits<C>::assign(q, 0, '0');
+  VERIFY( r == q );
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char32_t/65049.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char32_t/65049.cc
new file mode 100644 (file)
index 0000000..a7730ec
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+// libstdc++/65049
+
+#include <string>
+#include <testsuite_hooks.h>
+
+using C = char32_t;
+
+void
+test01()
+{
+  const C* p = 0;
+  C* q = 0;
+  auto c = std::char_traits<C>::compare(p, q, 0);
+  VERIFY( c == 0 );
+  auto r = std::char_traits<C>::find(p, 0, '0');
+  VERIFY( r == nullptr );
+  r = std::char_traits<C>::move(q, p, 0);
+  VERIFY( r == q );
+  r = std::char_traits<C>::copy(q, p, 0);
+  VERIFY( r == q );
+  r = std::char_traits<C>::assign(q, 0, '0');
+  VERIFY( r == q );
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/wchar_t/65049.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/wchar_t/65049.cc
new file mode 100644 (file)
index 0000000..22dfdf0
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+// libstdc++/65049
+
+#include <string>
+#include <testsuite_hooks.h>
+
+using C = wchar_t;
+
+void
+test01()
+{
+  const C* p = 0;
+  C* q = 0;
+  auto c = std::char_traits<C>::compare(p, q, 0);
+  VERIFY( c == 0 );
+  auto r = std::char_traits<C>::find(p, 0, '0');
+  VERIFY( r == nullptr );
+  r = std::char_traits<C>::move(q, p, 0);
+  VERIFY( r == q );
+  r = std::char_traits<C>::copy(q, p, 0);
+  VERIFY( r == q );
+  r = std::char_traits<C>::assign(q, 0, '0');
+  VERIFY( r == q );
+}
+
+int
+main()
+{
+  test01();
+}