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 <[email protected]>
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):