From 5040d6912ccf32e1b3baed1e0a2d9dd475bbf853 Mon Sep 17 00:00:00 2001 From: Petur Runolfsson Date: Fri, 7 Mar 2003 17:24:47 +0000 Subject: [PATCH] re PR libstdc++/9817 (collate::compare doesn't handle nul characters.) 2003-03-07 Petur Runolfsson PR libstdc++/9817 * include/bits/locale_facets.tcc (collate::do_compare, collate::do_transform): Handle nul characters in input. * testsuite/22_locale/collate/compare/char/3.cc: New test. * testsuite/22_locale/collate/compare/wchar_t/3.cc: New test. * testsuite/22_locale/collate/transform/char/3.cc: New test. * testsuite/22_locale/collate/transform/wchar_t/3.cc: New test. From-SVN: r63946 --- libstdc++-v3/ChangeLog | 11 +++ libstdc++-v3/include/bits/locale_facets.tcc | 74 ++++++++++++--- .../22_locale/collate/compare/char/3.cc | 90 ++++++++++++++++++ .../22_locale/collate/compare/wchar_t/3.cc | 90 ++++++++++++++++++ .../22_locale/collate/transform/char/3.cc | 93 +++++++++++++++++++ .../22_locale/collate/transform/wchar_t/3.cc | 93 +++++++++++++++++++ 6 files changed, 440 insertions(+), 11 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/collate/compare/char/3.cc create mode 100644 libstdc++-v3/testsuite/22_locale/collate/compare/wchar_t/3.cc create mode 100644 libstdc++-v3/testsuite/22_locale/collate/transform/char/3.cc create mode 100644 libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/3.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 2162fc8e70a..763b5739e51 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2003-03-07 Petur Runolfsson + + PR libstdc++/9817 + * include/bits/locale_facets.tcc + (collate::do_compare, collate::do_transform): + Handle nul characters in input. + * testsuite/22_locale/collate/compare/char/3.cc: New test. + * testsuite/22_locale/collate/compare/wchar_t/3.cc: New test. + * testsuite/22_locale/collate/transform/char/3.cc: New test. + * testsuite/22_locale/collate/transform/wchar_t/3.cc: New test. + 2003-03-07 Jerry Quinn * include/bits/streambuf_iterator.h (_M_put): Set _M_failed if diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index cb6dccd19e6..b5b1f5c2e1e 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -2038,9 +2038,37 @@ namespace std do_compare(const _CharT* __lo1, const _CharT* __hi1, const _CharT* __lo2, const _CharT* __hi2) const { + // strcoll assumes zero-terminated strings so we make a copy + // and then put a zero at the end. const string_type __one(__lo1, __hi1); const string_type __two(__lo2, __hi2); - return _M_compare(__one.c_str(), __two.c_str()); + + const _CharT* __p = __one.c_str(); + const _CharT* __pend = __one.c_str() + __one.length(); + const _CharT* __q = __two.c_str(); + const _CharT* __qend = __two.c_str() + __two.length(); + + // strcoll stops when it sees a nul character so we break + // the strings into zero-terminated substrings and pass those + // to strcoll. + for (;;) + { + int __res = _M_compare(__p, __q); + if (__res) + return __res; + + __p += char_traits<_CharT>::length(__p); + __q += char_traits<_CharT>::length(__q); + if (__p == __pend && __q == __qend) + return 0; + else if (__p == __pend) + return -1; + else if (__q == __qend) + return 1; + + __p++; + __q++; + } } template @@ -2048,19 +2076,43 @@ namespace std collate<_CharT>:: do_transform(const _CharT* __lo, const _CharT* __hi) const { + // strxfrm assumes zero-terminated strings so we make a copy + string_type __str(__lo, __hi); + + const _CharT* __p = __str.c_str(); + const _CharT* __pend = __str.c_str() + __str.length(); + size_t __len = (__hi - __lo) * 2; - // First try a buffer perhaps big enough. - _CharT* __c = - static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); - size_t __res = _M_transform(__c, __lo, __len); - // If the buffer was not large enough, try again with the correct size. - if (__res >= __len) + + string_type __ret; + + // strxfrm stops when it sees a nul character so we break + // the string into zero-terminated substrings and pass those + // to strxfrm. + for (;;) { - __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * (__res + 1))); - _M_transform(__c, __lo, __res + 1); + // First try a buffer perhaps big enough. + _CharT* __c = + static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); + size_t __res = _M_transform(__c, __p, __len); + // If the buffer was not large enough, try again with the + // correct size. + if (__res >= __len) + { + __len = __res + 1; + __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len)); + __res = _M_transform(__c, __p, __res + 1); + } + + __ret.append(__c, __res); + __p += char_traits<_CharT>::length(__p); + if (__p == __pend) + return __ret; + + __p++; + __ret.push_back(_CharT()); } - return string_type(__c); } template diff --git a/libstdc++-v3/testsuite/22_locale/collate/compare/char/3.cc b/libstdc++-v3/testsuite/22_locale/collate/compare/char/3.cc new file mode 100644 index 00000000000..0cce392824a --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/collate/compare/char/3.cc @@ -0,0 +1,90 @@ +// 2003-02-24 Petur Runolfsson + +// Copyright (C) 2003 Free Software Foundation +// +// 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 2, 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 COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 22.2.4.1.1 collate members + +#include +#include + +// Test handling of strings containing nul characters +void test03() +{ + using namespace std; + typedef std::collate::string_type string_type; + + bool test = true; + + // basic construction + locale loc_c = locale::classic(); + locale loc_de("de_DE"); + VERIFY( loc_c != loc_de ); + + // cache the collate facets + const collate& coll_c = use_facet >(loc_c); + const collate& coll_de = use_facet >(loc_de); + + // int compare(const charT*, const charT*, const charT*, const charT*) const + const char* strlit1 = "a\0a\0"; + const char* strlit2 = "a\0b\0"; + const char* strlit3 = "a\0\xc4\0"; + const char* strlit4 = "a\0B\0"; + const char* strlit5 = "aa\0"; + const char* strlit6 = "b\0a\0"; + + int i; + i = coll_c.compare(strlit1, strlit1 + 3, strlit2, strlit2 + 3); + VERIFY( i == -1 ); + + i = coll_de.compare(strlit1, strlit1 + 3, strlit2, strlit2 + 3); + VERIFY( i == -1 ); + + i = coll_c.compare(strlit3, strlit3 + 3, strlit4, strlit4 + 3); + VERIFY( i == 1 ); + + i = coll_de.compare(strlit3, strlit3 + 3, strlit4, strlit4 + 3); + VERIFY( i == -1 ); + + i = coll_c.compare(strlit1, strlit1 + 3, strlit1, strlit1 + 4); + VERIFY( i == -1 ); + + i = coll_de.compare(strlit3, strlit3 + 4, strlit3, strlit3 + 3); + VERIFY( i == 1 ); + + i = coll_c.compare(strlit1, strlit1 + 4, strlit4, strlit4 + 1); + VERIFY( i == 1 ); + + i = coll_de.compare(strlit3, strlit3 + 3, strlit3, strlit3 + 3); + VERIFY( i == 0 ); + + i = coll_c.compare(strlit1, strlit1 + 2, strlit1, strlit1 + 4); + VERIFY( i == -1 ); + + i = coll_de.compare(strlit1, strlit1 + 3, strlit5, strlit5 + 3); + VERIFY( i == -1 ); + + i = coll_c.compare(strlit6, strlit6 + 3, strlit1, strlit1 + 3); + VERIFY( i == 1 ); +} + +int main() +{ + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/collate/compare/wchar_t/3.cc b/libstdc++-v3/testsuite/22_locale/collate/compare/wchar_t/3.cc new file mode 100644 index 00000000000..0f9ee649c32 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/collate/compare/wchar_t/3.cc @@ -0,0 +1,90 @@ +// 2003-02-24 Petur Runolfsson + +// Copyright (C) 2003 Free Software Foundation +// +// 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 2, 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 COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 22.2.4.1.1 collate members + +#include +#include + +// Test handling of strings containing nul characters +void test03() +{ + using namespace std; + typedef std::collate::string_type string_type; + + bool test = true; + + // basic construction + locale loc_c = locale::classic(); + locale loc_de("de_DE"); + VERIFY( loc_c != loc_de ); + + // cache the collate facets + const collate& coll_c = use_facet >(loc_c); + const collate& coll_de = use_facet >(loc_de); + + // int compare(const charT*, const charT*, const charT*, const charT*) const + const wchar_t* strlit1 = L"a\0a\0"; + const wchar_t* strlit2 = L"a\0b\0"; + const wchar_t* strlit3 = L"a\0\xc4\0"; + const wchar_t* strlit4 = L"a\0B\0"; + const wchar_t* strlit5 = L"aa\0"; + const wchar_t* strlit6 = L"b\0a\0"; + + int i; + i = coll_c.compare(strlit1, strlit1 + 3, strlit2, strlit2 + 3); + VERIFY( i == -1 ); + + i = coll_de.compare(strlit1, strlit1 + 3, strlit2, strlit2 + 3); + VERIFY( i == -1 ); + + i = coll_c.compare(strlit3, strlit3 + 3, strlit4, strlit4 + 3); + VERIFY( i == 1 ); + + i = coll_de.compare(strlit3, strlit3 + 3, strlit4, strlit4 + 3); + VERIFY( i == -1 ); + + i = coll_c.compare(strlit1, strlit1 + 3, strlit1, strlit1 + 4); + VERIFY( i == -1 ); + + i = coll_de.compare(strlit3, strlit3 + 4, strlit3, strlit3 + 3); + VERIFY( i == 1 ); + + i = coll_c.compare(strlit1, strlit1 + 4, strlit4, strlit4 + 1); + VERIFY( i == 1 ); + + i = coll_de.compare(strlit3, strlit3 + 3, strlit3, strlit3 + 3); + VERIFY( i == 0 ); + + i = coll_c.compare(strlit1, strlit1 + 2, strlit1, strlit1 + 4); + VERIFY( i == -1 ); + + i = coll_de.compare(strlit1, strlit1 + 3, strlit5, strlit5 + 3); + VERIFY( i == -1 ); + + i = coll_c.compare(strlit6, strlit6 + 3, strlit1, strlit1 + 3); + VERIFY( i == 1 ); +} + +int main() +{ + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/collate/transform/char/3.cc b/libstdc++-v3/testsuite/22_locale/collate/transform/char/3.cc new file mode 100644 index 00000000000..a6255afb6c3 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/collate/transform/char/3.cc @@ -0,0 +1,93 @@ +// 2003-02-24 Petur Runolfsson + +// Copyright (C) 2003 Free Software Foundation +// +// 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 2, 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 COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 22.2.4.1.1 collate members + +#include +#include + +void test03() +{ + using namespace std; + typedef std::collate::string_type string_type; + + bool test = true; + + // basic construction + locale loc_c = locale::classic(); + locale loc_de("de_DE"); + VERIFY( loc_c != loc_de ); + + // cache the collate facets + const collate& coll_c = use_facet >(loc_c); + const collate& coll_de = use_facet >(loc_de); + + const char* strlit1 = "a\0a\0"; + const char* strlit2 = "a\0b\0"; + const char* strlit3 = "a\0\xc4\0"; + const char* strlit4 = "a\0B\0"; + const char* strlit5 = "aa\0"; + const char* strlit6 = "b\0a\0"; + + int i; + string_type str1; + string_type str2; + + str1 = coll_c.transform(strlit1, strlit1 + 3); + str2 = coll_c.transform(strlit2, strlit2 + 3); + i = str1.compare(str2); + VERIFY( i < 0 ); + + str1 = coll_de.transform(strlit1, strlit1 + 3); + str2 = coll_de.transform(strlit2, strlit2 + 3); + i = str1.compare(str2); + VERIFY( i < 0 ); + + str1 = coll_c.transform(strlit3, strlit3 + 3); + str2 = coll_c.transform(strlit4, strlit4 + 3); + i = str1.compare(str2); + VERIFY( i > 0 ); + + str1 = coll_de.transform(strlit3, strlit3 + 3); + str2 = coll_de.transform(strlit4, strlit4 + 3); + i = str1.compare(str2); + VERIFY( i < 0 ); + + str1 = coll_c.transform(strlit1, strlit1 + 1); + str2 = coll_c.transform(strlit5, strlit5 + 1); + i = str1.compare(str2); + VERIFY( i == 0 ); + + str1 = coll_de.transform(strlit6, strlit6 + 3); + str2 = coll_de.transform(strlit1, strlit1 + 3); + i = str1.compare(str2); + VERIFY( i > 0 ); + + str1 = coll_c.transform(strlit1, strlit1 + 3); + str2 = coll_c.transform(strlit5, strlit5 + 3); + i = str1.compare(str2); + VERIFY( i < 0 ); +} + +int main() +{ + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/3.cc b/libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/3.cc new file mode 100644 index 00000000000..108c0a4be30 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/3.cc @@ -0,0 +1,93 @@ +// 2003-02-24 Petur Runolfsson + +// Copyright (C) 2003 Free Software Foundation +// +// 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 2, 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 COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 22.2.4.1.1 collate members + +#include +#include + +void test03() +{ + using namespace std; + typedef std::collate::string_type string_type; + + bool test = true; + + // basic construction + locale loc_c = locale::classic(); + locale loc_de("de_DE"); + VERIFY( loc_c != loc_de ); + + // cache the collate facets + const collate& coll_c = use_facet >(loc_c); + const collate& coll_de = use_facet >(loc_de); + + const wchar_t* strlit1 = L"a\0a\0"; + const wchar_t* strlit2 = L"a\0b\0"; + const wchar_t* strlit3 = L"a\0\xc4\0"; + const wchar_t* strlit4 = L"a\0B\0"; + const wchar_t* strlit5 = L"aa\0"; + const wchar_t* strlit6 = L"b\0a\0"; + + int i; + string_type str1; + string_type str2; + + str1 = coll_c.transform(strlit1, strlit1 + 3); + str2 = coll_c.transform(strlit2, strlit2 + 3); + i = str1.compare(str2); + VERIFY( i < 0 ); + + str1 = coll_de.transform(strlit1, strlit1 + 3); + str2 = coll_de.transform(strlit2, strlit2 + 3); + i = str1.compare(str2); + VERIFY( i < 0 ); + + str1 = coll_c.transform(strlit3, strlit3 + 3); + str2 = coll_c.transform(strlit4, strlit4 + 3); + i = str1.compare(str2); + VERIFY( i > 0 ); + + str1 = coll_de.transform(strlit3, strlit3 + 3); + str2 = coll_de.transform(strlit4, strlit4 + 3); + i = str1.compare(str2); + VERIFY( i < 0 ); + + str1 = coll_c.transform(strlit1, strlit1 + 1); + str2 = coll_c.transform(strlit5, strlit5 + 1); + i = str1.compare(str2); + VERIFY( i == 0 ); + + str1 = coll_de.transform(strlit6, strlit6 + 3); + str2 = coll_de.transform(strlit1, strlit1 + 3); + i = str1.compare(str2); + VERIFY( i > 0 ); + + str1 = coll_c.transform(strlit1, strlit1 + 3); + str2 = coll_c.transform(strlit5, strlit5 + 3); + i = str1.compare(str2); + VERIFY( i < 0 ); +} + +int main() +{ + test03(); + return 0; +} -- 2.30.2