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):


Reply via email to