From: Jonathan Wakely Date: Mon, 24 Aug 2015 13:43:54 +0000 (+0100) Subject: re PR libstdc++/65049 (Undefined behaviour with std::char_traits) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4a88769c966c56816200b2ca128f7e66ce35862f;p=gcc.git re PR libstdc++/65049 (Undefined behaviour with std::char_traits) PR libstdc++/65049 * include/bits/char_traits.h (char_traits::compare, char_traits::find, char_traits::move, char_traits::copy, char_traits::assign): Check for zero length. (char_traits::compare, char_traits::find, char_traits::move, char_traits::copy, char_traits::assign): Likewise. (char_traits::move, char_traits::copy): Likewise. (char_traits::move, char_traits::copy): Likewise. * include/ext/pod_char_traits.h (char_traits>::move, char_traits>::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 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 090e8e3373a..f6f68a81301 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,25 @@ 2015-08-24 Jonathan Wakely + PR libstdc++/65049 + * include/bits/char_traits.h (char_traits::compare, + char_traits::find, char_traits::move, + char_traits::copy, char_traits::assign): Check for zero + length. + (char_traits::compare, char_traits::find, + char_traits::move, char_traits::copy, + char_traits::assign): Likewise. + (char_traits::move, char_traits::copy): Likewise. + (char_traits::move, char_traits::copy): Likewise. + * include/ext/pod_char_traits.h (char_traits>::move, + char_traits>::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. diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index 369c636d8fd..0d0063bcee6 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -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(__builtin_memchr(__s, __a, __n)); } + { + if (__n == 0) + return 0; + return static_cast(__builtin_memchr(__s, __a, __n)); + } static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) - { return static_cast(__builtin_memmove(__s1, __s2, __n)); } + { + if (__n == 0) + return __s1; + return static_cast(__builtin_memmove(__s1, __s2, __n)); + } static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) - { return static_cast(__builtin_memcpy(__s1, __s2, __n)); } + { + if (__n == 0) + return __s1; + return static_cast(__builtin_memcpy(__s1, __s2, __n)); + } static char_type* assign(char_type* __s, size_t __n, char_type __a) - { return static_cast(__builtin_memset(__s, __a, __n)); } + { + if (__n == 0) + return __s; + return static_cast(__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 (__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 (__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 (__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 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); } diff --git a/libstdc++-v3/include/ext/pod_char_traits.h b/libstdc++-v3/include/ext/pod_char_traits.h index c941080f54a..38a84c80d5b 100644 --- a/libstdc++-v3/include/ext/pod_char_traits.h +++ b/libstdc++-v3/include/ext/pod_char_traits.h @@ -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 (__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 index 00000000000..1aa00ddc1fc --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char/65049.cc @@ -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 +// . + +// { dg-options "-std=gnu++11" } + +// libstdc++/65049 + +#include +#include + +using C = char; + +void +test01() +{ + const C* p = 0; + C* q = 0; + auto c = std::char_traits::compare(p, q, 0); + VERIFY( c == 0 ); + auto r = std::char_traits::find(p, 0, '0'); + VERIFY( r == nullptr ); + r = std::char_traits::move(q, p, 0); + VERIFY( r == q ); + r = std::char_traits::copy(q, p, 0); + VERIFY( r == q ); + r = std::char_traits::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 index 00000000000..7af6db3ff42 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char16_t/65049.cc @@ -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 +// . + +// { dg-options "-std=gnu++11" } + +// libstdc++/65049 + +#include +#include + +using C = char16_t; + +void +test01() +{ + const C* p = 0; + C* q = 0; + auto c = std::char_traits::compare(p, q, 0); + VERIFY( c == 0 ); + auto r = std::char_traits::find(p, 0, '0'); + VERIFY( r == nullptr ); + r = std::char_traits::move(q, p, 0); + VERIFY( r == q ); + r = std::char_traits::copy(q, p, 0); + VERIFY( r == q ); + r = std::char_traits::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 index 00000000000..a7730ec2582 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/char32_t/65049.cc @@ -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 +// . + +// { dg-options "-std=gnu++11" } + +// libstdc++/65049 + +#include +#include + +using C = char32_t; + +void +test01() +{ + const C* p = 0; + C* q = 0; + auto c = std::char_traits::compare(p, q, 0); + VERIFY( c == 0 ); + auto r = std::char_traits::find(p, 0, '0'); + VERIFY( r == nullptr ); + r = std::char_traits::move(q, p, 0); + VERIFY( r == q ); + r = std::char_traits::copy(q, p, 0); + VERIFY( r == q ); + r = std::char_traits::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 index 00000000000..22dfdf03513 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/wchar_t/65049.cc @@ -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 +// . + +// { dg-options "-std=gnu++11" } + +// libstdc++/65049 + +#include +#include + +using C = wchar_t; + +void +test01() +{ + const C* p = 0; + C* q = 0; + auto c = std::char_traits::compare(p, q, 0); + VERIFY( c == 0 ); + auto r = std::char_traits::find(p, 0, '0'); + VERIFY( r == nullptr ); + r = std::char_traits::move(q, p, 0); + VERIFY( r == q ); + r = std::char_traits::copy(q, p, 0); + VERIFY( r == q ); + r = std::char_traits::assign(q, 0, '0'); + VERIFY( r == q ); +} + +int +main() +{ + test01(); +}