From bb393514d5be4d683a72fa4bfda938943368505a Mon Sep 17 00:00:00 2001 From: Ed Smith-Rowland <3dw4rd@verizon.net> Date: Fri, 24 Jan 2014 20:15:00 +0000 Subject: [PATCH] re PR libstdc++/59531 (string_view overrun in copy operation) 2014-01-24 Ed Smith-Rowland <3dw4rd@verizon.net> PR libstdc++/59531 * testsuite/experimental/string_view/operations/copy/char/1.cc: New. * testsuite/experimental/string_view/operations/copy/wchar_t/1.cc: New. 2014-01-24 Ed Smith-Rowland <3dw4rd@verizon.net> Peter A. Bigot PR libstdc++/59531 * include/experimental/string_view (copy(_CharT*, size_type, size_type) const): Correct throw string. Correct copy start location. 2014-01-24 Ed Smith-Rowland <3dw4rd@verizon.net> Peter A. Bigot PR libstdc++/59530 * include/experimental/string_view (operator[](size_type) const): Fix one-off index error in debug check. * testsuite/experimental/string_view/element_access/char/1.cc: Don't test basic_string_view at size(). * testsuite/experimental/string_view/element_access/wchar_t/1.cc: Ditto. 2014-01-24 Ed Smith-Rowland <3dw4rd@verizon.net> Peter A. Bigot PR libstdc++/59529 * include/experimental/string_view (basic_string_view(const _CharT*, size_type)): Don't care if len == 0. * testsuite/experimental/string_view/operations/substr/char/1.cc: Comment out catch of out_of_range; No terminating null in basic_string_view. Check begin == end. * testsuite/experimental/string_view/operations/substr/wchar_t/1.cc: Ditto. Co-Authored-By: Peter A. Bigot From-SVN: r207060 --- libstdc++-v3/ChangeLog | 36 +++++++++++++ libstdc++-v3/include/experimental/string_view | 18 +++---- .../string_view/element_access/char/1.cc | 5 +- .../string_view/element_access/wchar_t/1.cc | 5 +- .../string_view/operations/copy/char/1.cc | 50 ++++++++++++++++++ .../string_view/operations/copy/wchar_t/1.cc | 51 +++++++++++++++++++ .../string_view/operations/substr/char/1.cc | 6 +-- .../operations/substr/wchar_t/1.cc | 6 +-- 8 files changed, 156 insertions(+), 21 deletions(-) create mode 100644 libstdc++-v3/testsuite/experimental/string_view/operations/copy/char/1.cc create mode 100644 libstdc++-v3/testsuite/experimental/string_view/operations/copy/wchar_t/1.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 30e4f22b8c8..b575a92f5c4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,39 @@ +2014-01-24 Ed Smith-Rowland <3dw4rd@verizon.net> + + PR libstdc++/59531 + * testsuite/experimental/string_view/operations/copy/char/1.cc: New. + * testsuite/experimental/string_view/operations/copy/wchar_t/1.cc: New. + +2014-01-24 Ed Smith-Rowland <3dw4rd@verizon.net> + Peter A. Bigot + + PR libstdc++/59531 + * include/experimental/string_view + (copy(_CharT*, size_type, size_type) const): Correct throw string. + Correct copy start location. + +2014-01-24 Ed Smith-Rowland <3dw4rd@verizon.net> + Peter A. Bigot + + PR libstdc++/59530 + * include/experimental/string_view (operator[](size_type) const): + Fix one-off index error in debug check. + * testsuite/experimental/string_view/element_access/char/1.cc: Don't + test basic_string_view at size(). + * testsuite/experimental/string_view/element_access/wchar_t/1.cc: Ditto. + +2014-01-24 Ed Smith-Rowland <3dw4rd@verizon.net> + Peter A. Bigot + + PR libstdc++/59529 + * include/experimental/string_view + (basic_string_view(const _CharT*, size_type)): Don't care if len == 0. + * testsuite/experimental/string_view/operations/substr/char/1.cc: + Comment out catch of out_of_range; No terminating null + in basic_string_view. Check begin == end. + * testsuite/experimental/string_view/operations/substr/wchar_t/1.cc: + Ditto. + 2014-01-24 Jonathan Wakely PR libstdc++/59548 diff --git a/libstdc++-v3/include/experimental/string_view b/libstdc++-v3/include/experimental/string_view index ab6943d806b..bebeb6b62ea 100644 --- a/libstdc++-v3/include/experimental/string_view +++ b/libstdc++-v3/include/experimental/string_view @@ -117,7 +117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr basic_string_view(const _CharT* __str, size_type __len) : _M_len{__str == nullptr ? 0 :__len}, - _M_str{__str == nullptr || __len == 0 ? _S_empty_str : __str} + _M_str{__str == nullptr ? _S_empty_str : __str} { } basic_string_view& @@ -182,7 +182,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator[](size_type __pos) const { // TODO: Assert to restore in a way compatible with the constexpr. - // _GLIBCXX_DEBUG_ASSERT(__pos <= this->_M_len); + // _GLIBCXX_DEBUG_ASSERT(__pos < this->_M_len); return *(this->_M_str + __pos); } @@ -259,14 +259,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION copy(_CharT* __str, size_type __n, size_type __pos = 0) const { __glibcxx_requires_string_len(__str, __n); - if (__pos >= this->_M_len) - __throw_out_of_range_fmt(__N("basic_string_view::at: __pos " - "(which is %zu) >= this->size() " + if (__pos > this->_M_len) + __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos " + "(which is %zu) > this->size() " "(which is %zu)"), __pos, this->size()); size_type __rlen{std::min(__n, size_type{this->_M_len - __pos})}; for (auto __begin = this->_M_str + __pos, - __end = this->_M_str + __rlen; __begin != __end;) + __end = __begin + __rlen; __begin != __end;) *__str++ = *__begin++; return __rlen; } @@ -277,11 +277,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr basic_string_view substr(size_type __pos, size_type __n=npos) const { - return __pos < this->_M_len + return __pos <= this->_M_len ? basic_string_view{this->_M_str + __pos, std::min(__n, size_type{this->_M_len - __pos})} - : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos " - "(which is %zu) >= this->size() " + : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos " + "(which is %zu) > this->size() " "(which is %zu)"), __pos, this->size()), basic_string_view{}); } diff --git a/libstdc++-v3/testsuite/experimental/string_view/element_access/char/1.cc b/libstdc++-v3/testsuite/experimental/string_view/element_access/char/1.cc index 562ed20bc53..0a0b19f60be 100644 --- a/libstdc++-v3/testsuite/experimental/string_view/element_access/char/1.cc +++ b/libstdc++-v3/testsuite/experimental/string_view/element_access/char/1.cc @@ -41,8 +41,9 @@ test01() csz01 = str01.size(); cref cref1 = str01[csz01 - 1]; VERIFY( cref1 == 'a' ); - cref cref2 = str01[csz01]; - VERIFY( cref2 == char() ); + // Undefined behavior at size(). + //cref cref2 = str01[csz01]; + //VERIFY( cref2 == char() ); // const_reference at(size_type pos) const; csz01 = str01.size(); diff --git a/libstdc++-v3/testsuite/experimental/string_view/element_access/wchar_t/1.cc b/libstdc++-v3/testsuite/experimental/string_view/element_access/wchar_t/1.cc index e125c03e5ee..e3df84d41f0 100644 --- a/libstdc++-v3/testsuite/experimental/string_view/element_access/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/experimental/string_view/element_access/wchar_t/1.cc @@ -41,8 +41,9 @@ test01() csz01 = str01.size(); cref cref1 = str01[csz01 - 1]; VERIFY( cref1 == L'a' ); - cref cref2 = str01[csz01]; - VERIFY( cref2 == wchar_t() ); + // Undefined behavior at size(). + //cref cref2 = str01[csz01]; + //VERIFY( cref2 == wchar_t() ); // const_reference at(size_type pos) const; csz01 = str01.size(); diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/copy/char/1.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/copy/char/1.cc new file mode 100644 index 00000000000..25b2af133d3 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/string_view/operations/copy/char/1.cc @@ -0,0 +1,50 @@ +// { dg-options "-std=gnu++1y" } + +// Copyright (C) 2013 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 +// . + +// basic_string_view::copy + +#include +#include +#include + +bool +test01() +{ + bool test [[gnu::unused]] = true; + + typedef std::experimental::string_view::size_type csize_type; + + const char str_lit01[] = "123456789A"; + const std::experimental::string_view str01(str_lit01); + char buffer[4] = { 0 }; + + csize_type len = str01.copy(buffer, sizeof(buffer), 8); + VERIFY( 2 == len ); + VERIFY( '9' == buffer[0] ); + + return test; +} + +int +main() +{ + test01(); + + return 0; +} diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/copy/wchar_t/1.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/copy/wchar_t/1.cc new file mode 100644 index 00000000000..0348e1f98fc --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/string_view/operations/copy/wchar_t/1.cc @@ -0,0 +1,51 @@ +// { dg-options "-std=gnu++1y" } + +// Copyright (C) 2013 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 +// . + +// basic_string_view::copy + +#include +#include +#include + +bool +test01() +{ + bool test [[gnu::unused]] = true; + + typedef std::experimental::wstring_view::size_type csize_type; + csize_type csz01; + + const wchar_t str_lit01[] = L"123456789A"; + const std::experimental::wstring_view str01(str_lit01); + wchar_t buffer[4] = { 0 }; + + csize_type len = str01.copy(buffer, sizeof(buffer), 8); + VERIFY( 2 == len ); + VERIFY( L'9' == buffer[0] ); + + return test; +} + +int +main() +{ + test01(); + + return 0; +} diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/substr/char/1.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/substr/char/1.cc index 1cd03f49611..2f430ba1652 100644 --- a/libstdc++-v3/testsuite/experimental/string_view/operations/substr/char/1.cc +++ b/libstdc++-v3/testsuite/experimental/string_view/operations/substr/char/1.cc @@ -63,10 +63,8 @@ test01() { str02 = str01.substr(csz01); VERIFY( str02.size() == 0 ); - } - catch(std::out_of_range& fail) - { - VERIFY( true ); // No terminating null in basic_string_view + VERIFY( str02.begin() == str01.end() ); + VERIFY( true ); } catch(...) { diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/substr/wchar_t/1.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/substr/wchar_t/1.cc index e81844a21f4..6be8838e0d2 100644 --- a/libstdc++-v3/testsuite/experimental/string_view/operations/substr/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/experimental/string_view/operations/substr/wchar_t/1.cc @@ -63,10 +63,8 @@ test01() { str02 = str01.substr(csz01); VERIFY( str02.size() == 0 ); - } - catch(std::out_of_range& fail) - { - VERIFY( true ); // No terminating null in basic_string_view + VERIFY( str02.begin() == str01.end() ); + VERIFY( true ); } catch(...) {