diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-02-23 03:01:59 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-02-23 03:01:59 +0000 |
commit | ace857f95d819377507f81ff4fc88ebf8b913eef (patch) | |
tree | 9bda6298fff3246b502dd0c0e4c2db91fb0c6e96 | |
parent | c1753302087205dd9d5e9013c859623b261df060 (diff) | |
download | gcc-ace857f95d819377507f81ff4fc88ebf8b913eef.zip gcc-ace857f95d819377507f81ff4fc88ebf8b913eef.tar.gz gcc-ace857f95d819377507f81ff4fc88ebf8b913eef.tar.bz2 |
PR libstdc++/89446 fix null pointer dereference in char_traits
PR libstdc++/89446
* include/bits/char_traits.h (__constant_char_array): Check index is
in range before dereferencing.
(char_traits<char>::compare, char_traits<char>::find)
(char_traits<char8_t>::compare, char_traits<char8_t>::find): Return
immediately if n is zero.
(char_traits<wchar_t>::compare, char_traits<wchar_t>::find): Likewise.
Remove workarounds for PR 67026.
* testsuite/21_strings/basic_string_view/operators/char/89446.cc:
New test.
* testsuite/21_strings/basic_string_view/operators/wchar_t/89446.cc:
New test.
From-SVN: r269148
4 files changed, 87 insertions, 19 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0e86053..4596af8 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,18 @@ +2019-02-23 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/89446 + * include/bits/char_traits.h (__constant_char_array): Check index is + in range before dereferencing. + (char_traits<char>::compare, char_traits<char>::find) + (char_traits<char8_t>::compare, char_traits<char8_t>::find): Return + immediately if n is zero. + (char_traits<wchar_t>::compare, char_traits<wchar_t>::find): Likewise. + Remove workarounds for PR 67026. + * testsuite/21_strings/basic_string_view/operators/char/89446.cc: + New test. + * testsuite/21_strings/basic_string_view/operators/wchar_t/89446.cc: + New test. + 2019-02-22 Eric Botcazou <ebotcazou@adacore.com> * config/abi/post/sparc64-linux-gnu/baseline_symbols.txt: Adjust. diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index 21099c3..fd9a3c7 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -260,7 +260,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __builtin_is_constant_evaluated(); #else size_t __i = 0; - while (__builtin_constant_p(__a[__i]) && __i < __n) + while (__i < __n && __builtin_constant_p(__a[__i])) __i++; return __i == __n; #endif @@ -314,14 +314,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 >= 201703L 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); } @@ -338,14 +338,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX17_CONSTEXPR const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { + if (__n == 0) + return 0; #if __cplusplus >= 201703L if (__builtin_constant_p(__n) && __builtin_constant_p(__a) && __constant_char_array_p(__s, __n)) return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); #endif - if (__n == 0) - return 0; return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); } @@ -423,16 +423,15 @@ _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 >= 201703L 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; - else - return wmemcmp(__s1, __s2, __n); + return wmemcmp(__s1, __s2, __n); } static _GLIBCXX17_CONSTEXPR size_t @@ -441,24 +440,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201703L if (__constant_string_p(__s)) return __gnu_cxx::char_traits<char_type>::length(__s); - else #endif - return wcslen(__s); + return wcslen(__s); } static _GLIBCXX17_CONSTEXPR const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { + if (__n == 0) + return 0; #if __cplusplus >= 201703L if (__builtin_constant_p(__n) && __builtin_constant_p(__a) && __constant_char_array_p(__s, __n)) return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); #endif - if (__n == 0) - return 0; - else - return wmemchr(__s, __a, __n); + return wmemchr(__s, __a, __n); } static char_type* @@ -532,14 +529,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); } @@ -559,14 +556,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX17_CONSTEXPR const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { + if (__n == 0) + return 0; #if __cplusplus > 201402 if (__builtin_constant_p(__n) && __builtin_constant_p(__a) && __constant_char_array_p(__s, __n)) return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); #endif - if (__n == 0) - return 0; return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/89446.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/89446.cc new file mode 100644 index 0000000..768ba63 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/char/89446.cc @@ -0,0 +1,28 @@ +// Copyright (C) 2019 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++17 -fexceptions -fnon-call-exceptions -O1" } +// { dg-do run { target { powerpc*-*-linux* i?86-*-linux* x86_64-*-linux* } } } +// { dg-require-effective-target c++17 } + +#include <string_view> + +int main() +{ + std::string_view s1, s2; + return s1 != s2; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/89446.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/89446.cc new file mode 100644 index 0000000..a0ecbeb --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operators/wchar_t/89446.cc @@ -0,0 +1,28 @@ +// Copyright (C) 2019 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++17 -fexceptions -fnon-call-exceptions -O1" } +// { dg-do run { target { powerpc*-*-linux* i?86-*-linux* x86_64-*-linux* } } } +// { dg-require-effective-target c++17 } + +#include <string_view> + +int main() +{ + std::wstring_view s1, s2; + return s1 != s2; +} |