Author: faridz Date: Sun Feb 19 18:50:50 2012 New Revision: 1291038 URL: http://svn.apache.org/viewvc?rev=1291038&view=rev Log: 2012-02-19 Farid Zaripov <far...@apache.com>
STDCXX-1060 * include/string.cc (append): Avoid arithmetic overflow in calculating of new size. * tests/regress/21.string.append.stdcxx-1060.cpp: New regression test is added. * tests/strings/21.string.append.cpp: Added test cases to exercise STDCXX-1060. Added: stdcxx/branches/4.2.x/tests/regress/21.string.append.stdcxx-1060.cpp (with props) Modified: stdcxx/branches/4.2.x/include/string stdcxx/branches/4.2.x/tests/strings/21.string.append.cpp Modified: stdcxx/branches/4.2.x/include/string URL: http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/include/string?rev=1291038&r1=1291037&r2=1291038&view=diff ============================================================================== --- stdcxx/branches/4.2.x/include/string (original) +++ stdcxx/branches/4.2.x/include/string Sun Feb 19 18:50:50 2012 @@ -1222,12 +1222,12 @@ basic_string<_CharT, _Traits, _Allocator append (const_pointer __s, size_type __n) { const size_type __size0 = size (); - const _RWSTD_SIZE_T __size1 = __size0 + __n; - if ( capacity () <= __size1 + if ( capacity () - __size0 < __n || size_type (1) < size_type (_C_pref ()->_C_get_ref ())) - return replace (size (), size_type (), __s, __n); + return replace (__size0, size_type (), __s, __n); + const _RWSTD_SIZE_T __size1 = __size0 + __n; traits_type::copy (_C_data + __size0, __s, __n); traits_type::assign (_C_data [__size1], value_type ()); _C_pref ()->_C_size._C_size = __size1; @@ -1242,12 +1242,12 @@ basic_string<_CharT, _Traits, _Allocator append (size_type __n, value_type __c) { const size_type __size0 = size (); - const _RWSTD_SIZE_T __size1 = __size0 + __n; - if ( capacity () < __size1 + if ( capacity () - __size0 < __n || size_type (1) < size_type (_C_pref ()->_C_get_ref ())) - return replace (size (), size_type (), __n, __c); + return replace (__size0, size_type (), __n, __c); + const _RWSTD_SIZE_T __size1 = __size0 + __n; traits_type::assign (_C_data + __size0, __n, __c); traits_type::assign (_C_data [__size1], value_type ()); _C_pref ()->_C_size._C_size = __size1; Added: stdcxx/branches/4.2.x/tests/regress/21.string.append.stdcxx-1060.cpp URL: http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/tests/regress/21.string.append.stdcxx-1060.cpp?rev=1291038&view=auto ============================================================================== --- stdcxx/branches/4.2.x/tests/regress/21.string.append.stdcxx-1060.cpp (added) +++ stdcxx/branches/4.2.x/tests/regress/21.string.append.stdcxx-1060.cpp Sun Feb 19 18:50:50 2012 @@ -0,0 +1,112 @@ +/************************************************************************ +* +* 21.string.append.stdcxx-1060.cpp - test case from STDCXX-1060 issue +* +* $Id$ +* +*************************************************************************** +* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed +* with this work for additional information regarding copyright +* ownership. The ASF licenses this file to you under the Apache +* License, Version 2.0 (the "License"); you may not use this file +* except in compliance with the License. You may obtain a copy of +* the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +* implied. See the License for the specific language governing +* permissions and limitations under the License. +* +**************************************************************************/ + +#include <cassert> +#include <cstddef> +#include <string> +#include <stdexcept> + +template <class ch> +struct my_traits : std::char_traits<ch> +{ + using std::char_traits<ch>::char_type; + using std::char_traits<ch>::int_type; + using std::char_traits<ch>::off_type; + using std::char_traits<ch>::state_type; + using std::char_traits<ch>::pos_type; + + using std::char_traits<ch>::eof; + using std::char_traits<ch>::assign; + using std::char_traits<ch>::eq; + using std::char_traits<ch>::lt; + using std::char_traits<ch>::compare; + using std::char_traits<ch>::find; + using std::char_traits<ch>::length; + using std::char_traits<ch>::move; + using std::char_traits<ch>::copy; + using std::char_traits<ch>::eq_int_type; + using std::char_traits<ch>::not_eof; + using std::char_traits<ch>::to_char_type; + using std::char_traits<ch>::to_int_type; + + static ch* copy (ch* dst, const ch* src, std::size_t n); + static ch* assign (ch* s, std::size_t n, ch c); +}; + +typedef std::basic_string<char, my_traits<char> > my_string; + +std::size_t throw_size; + +template <class ch> +ch* my_traits<ch>::copy (ch* dst, const ch* src, std::size_t n) +{ + if (throw_size == n) + throw n; + return std::char_traits<ch>::copy(dst, src, n); +} + +template <class ch> +ch* my_traits<ch>::assign (ch* s, std::size_t n, ch c) +{ + if (throw_size == n) + throw n; + return std::char_traits<ch>::assign (s, n, c); +} + +void test (std::size_t size) +{ + my_string s (5, 'a'); + throw_size = size; + + try { + s.append ("a", size); + assert (my_string::npos == size || !"Expect length error, got nothing"); + } + catch (std::length_error&) { + } + catch (...) { + assert (!"Expect length error, got other exception"); + } + + try { + s.append (size, 'a'); + assert (!"Expect length error, got nothing"); + } + catch (std::length_error&) { + } + catch (...) { + assert (!"Expect length error, got other exception"); + } +} + +int main () +{ + test (my_string().max_size() + 1); + test (my_string::npos - 1); + test (my_string::npos); + + return 0; +} Propchange: stdcxx/branches/4.2.x/tests/regress/21.string.append.stdcxx-1060.cpp ------------------------------------------------------------------------------ svn:eol-style = native Propchange: stdcxx/branches/4.2.x/tests/regress/21.string.append.stdcxx-1060.cpp ------------------------------------------------------------------------------ svn:keywords = Id Modified: stdcxx/branches/4.2.x/tests/strings/21.string.append.cpp URL: http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/tests/strings/21.string.append.cpp?rev=1291038&r1=1291037&r2=1291038&view=diff ============================================================================== --- stdcxx/branches/4.2.x/tests/strings/21.string.append.cpp (original) +++ stdcxx/branches/4.2.x/tests/strings/21.string.append.cpp Sun Feb 19 18:50:50 2012 @@ -264,6 +264,9 @@ cptr_size_test_cases [] = { TEST ("", "x@4096", 4096, "x@4096", 0), TEST ("x@4096", "", 0, "x@4096", 0), + TEST ("abc", "d", -1, "abc", 2), + TEST ("a@16", "d", -1, "a@16", 2), + TEST ("last", "test", 4, "lasttest", 0) }; @@ -429,6 +432,9 @@ size_val_test_cases [] = { TEST ("x@3694", 1, 'x', "x@3695", 0), TEST ("x@540", 1, 'x', "x@541", 0), + TEST ("ab", -1, 'c', "ab", 2), + TEST ("a@16", -1, 'c', "a@16", 2), + TEST ("last", 4, 't', "lasttttt", 0) }; @@ -586,9 +592,10 @@ void test_append (charT*, Traits*, Alloc // the state of the object after an exception) const StringState str_state (rw_get_string_state (str)); - const charT* const ptr_arg = tcase.arg ? arg.c_str () : str.c_str (); - const String& str_arg = tcase.arg ? arg : str; - const charT val_arg = (make_char (char (tcase.val), (charT*)0)); + const charT* const ptr_arg = tcase.arg ? arg.c_str () : str.c_str (); + const String& str_arg = tcase.arg ? arg : str; + const charT val_arg = (make_char (char (tcase.val), (charT*)0)); + const SizeT size_arg = 0 <= tcase.size ? tcase.size : str.max_size () + 1; std::size_t total_length_calls = 0; std::size_t n_length_calls = 0; @@ -657,7 +664,7 @@ void test_append (charT*, Traits*, Alloc break; case Append (cptr_size): - ret_ptr = &str.append (ptr_arg, tcase.size); + ret_ptr = &str.append (ptr_arg, size_arg); break; case Append (cstr_size_size): @@ -666,7 +673,7 @@ void test_append (charT*, Traits*, Alloc break; case Append (size_val): - ret_ptr = &str.append (tcase.size, val_arg); + ret_ptr = &str.append (size_arg, val_arg); break; case Append (range):