You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@stdcxx.apache.org by Travis Vitek <tv...@quovadx.com> on 2007/09/20 20:58:47 UTC

[PATCH] Add overflow checking to basic_string append and push_back

It appears that recent changes to string have accidentally removed some
overflow checking that used to be in the basic_string::append() and
push_back() methods. The following patch adds the checks back in.

Travis


2007-09-20  Travis Vitek  <vi...@roguewave.com>

	* string (append): add integer overflow check
	(push_back): Same

===================================================================
--- string	(revision 576541)
+++ string	(working copy)
@@ -1088,6 +1088,11 @@
 inline void basic_string<_CharT, _Traits, _Allocator>::
 push_back (value_type __c)
 {
+    _RWSTD_REQUIRES (size () <= max_size () - 1,
+                     (_RWSTD_ERROR_LENGTH_ERROR,
+                      _RWSTD_FUNC ("basic_string::append(value_type)"),
+                      size (), max_size () - 1));
+
     const size_type __size = size () + 1;
 
     if (   capacity () < __size
@@ -1095,7 +1100,6 @@
         append (1, __c);
     else {
         traits_type::assign (_C_data [size ()], __c);
-        // append the terminating NUL character
         traits_type::assign (_C_data [__size], value_type ());
         _C_pref ()->_C_size._C_size = __size;
     }
@@ -1196,6 +1200,12 @@
 basic_string<_CharT, _Traits, _Allocator>::
 append (const_pointer __s, size_type __n)
 {
+    _RWSTD_REQUIRES (size () <= max_size () - __n,
+                     (_RWSTD_ERROR_LENGTH_ERROR,
+                      _RWSTD_FUNC
("basic_string::append(const_pointer,"
+                                   " size_type)"),
+                      size (), max_size () - __n));
+
     const size_type __newsize = size () + __n;
 
     if (   capacity () <= __newsize

Re: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
> Stupid outlook.
>  
>> [21.3.5.2 p4] Effects: Determines the effective length rlen of the
>> string to append as the smaller of n and str.size() - pos. The function
>> then throws length_error if size() >= npos - rlen.
>>
>> The append that I'm invoking is described to behave as if it had called
>> that function.

Not quite. It's described to *return the same value* as the other
one. There's a subtle but important difference -- see issue 625:
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#625

But I agree, both calls to append() in your test case should throw
length_error due to 21.3, 4a) and irrespective of the issue.

That being said, rather than bloating the inline function by adding
a _RWSTD_REQUIRES() statement I wonder if we could achieve the same
effect by using size_t instead of size_type. The patch below fixed
the problem in the recently changed overload of append().

However, I suspect this (the absence of overflow handling) is
a pervasive problem throughout all of string and probably also
throughout the rest of our containers. So I think we should try
address it consistently throughout the whole library instead of
on a case by cases basis. If you agree, I suggest you create an
issue in Jira and schedule it for some release after 4.2.

Martin

Index: /nfs/homes/sebor/stdcxx/include/string
===================================================================
--- /nfs/homes/sebor/stdcxx/include/string      (revision 577852)
+++ /nfs/homes/sebor/stdcxx/include/string      (working copy)
@@ -1196,7 +1196,7 @@
  basic_string<_CharT, _Traits, _Allocator>::
  append (const_pointer __s, size_type __n)
  {
-    const size_type __newsize = size () + __n;
+    const _RWSTD_SIZE_T __newsize = size () + __n;

      if (   capacity () <= __newsize
          || size_type (1) < size_type (_C_pref ()->_C_get_ref ()))



>> The attached test case shows that we are not following
>> through on that requirement.
>>
> 
> #include <string>
> #include <stdexcept>
> 
> template <class T>
> struct Xallocator: std::allocator<T>
> {
>     //typedef typename std::allocator<T>::size_type size_type;
>     typedef unsigned char size_type;
> 
>     Xallocator (): std::allocator<T>() { } 
>     Xallocator (const Xallocator &rhs): std::allocator<T>(rhs) { }
>     template <class U>
>     Xallocator (const Xallocator<U> &rhs): std::allocator<T>(rhs) { }
> 
>     template <class U> 
>     struct rebind { typedef Xallocator<U> other; };
> 
>     size_type max_size () const { return 255; }
> };
> 
> typedef std::basic_string<char, std::char_traits<char>, Xallocator<char>
> String;
> 
> 
> #include <stdio.h>
> #include <assert.h>
> 
> int main()
> {
>     bool throw_required = false;
>     bool throw_happened = false;
> 
>     try {
>         String a (240, 'a');
>         String b ( 20, 'b');
> 
>         const String::size_type rlen = b.size();
> 
>         if (a.size () >= String::npos - rlen)
>             throw_required = true;
> 
>         // this throws correctly
>         //a.append (b, 0, String::npos);
> 
>         // this does not
>         a.append (b.c_str (), b.size ());
> 
>         // yet they are supposed to be equivalent
>     }
>     catch (const std::length_error&) {
>         throw_happened = true;
>     }
>     catch (...) {
>     }
> 
>     if (throw_required) {
>         assert (throw_happened);
>     }
> 
>     return 0;
> }


RE: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Travis Vitek <tv...@quovadx.com>.
Stupid outlook.
 
>
>[21.3.5.2 p4] Effects: Determines the effective length rlen of the
>string to append as the smaller of n and str.size() - pos. The function
>then throws length_error if size() >= npos - rlen.
>
>The append that I'm invoking is described to behave as if it had called
>that function. The attached test case shows that we are not following
>through on that requirement.
>

#include <string>
#include <stdexcept>

template <class T>
struct Xallocator: std::allocator<T>
{
    //typedef typename std::allocator<T>::size_type size_type;
    typedef unsigned char size_type;

    Xallocator (): std::allocator<T>() { } 
    Xallocator (const Xallocator &rhs): std::allocator<T>(rhs) { }
    template <class U>
    Xallocator (const Xallocator<U> &rhs): std::allocator<T>(rhs) { }

    template <class U> 
    struct rebind { typedef Xallocator<U> other; };

    size_type max_size () const { return 255; }
};

typedef std::basic_string<char, std::char_traits<char>, Xallocator<char>
>
String;


#include <stdio.h>
#include <assert.h>

int main()
{
    bool throw_required = false;
    bool throw_happened = false;

    try {
        String a (240, 'a');
        String b ( 20, 'b');

        const String::size_type rlen = b.size();

        if (a.size () >= String::npos - rlen)
            throw_required = true;

        // this throws correctly
        //a.append (b, 0, String::npos);

        // this does not
        a.append (b.c_str (), b.size ());

        // yet they are supposed to be equivalent
    }
    catch (const std::length_error&) {
        throw_happened = true;
    }
    catch (...) {
    }

    if (throw_required) {
        assert (throw_happened);
    }

    return 0;
}

RE: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Travis Vitek <tv...@quovadx.com>.
 

Martin Sebor wrote:
>
>Travis Vitek wrote:
>>
>> template <class _TypeT>
>> class Xallocator
>> {
>> public:
>>     typedef unsigned char       size_type;
>
>I suspect the problem might actually be here. Once you define
>size_type to a type with a more generous range the test case
>passes. I made this and a few other simplifying changes in
>the attached program (it's also possible that I messed
>something up in the process ;-)
>

[21.3.5.2 p4] Effects: Determines the effective length rlen of the
string to append as the smaller of n and str.size() - pos. The function
then throws length_error if size() >= npos - rlen.

The append that I'm invoking is described to behave as if it had called
that function. The attached test case shows that we are not following
through on that requirement.

>
>I agree that this is at least a theoretical problem (I can't
>quite imagine a practical use case for size_type being only
>8 bits wide). It might be an interesting exercise to change
>string (and the other containers) to work correctly even
>with size_type this small so long as it doesn't pessimize
>the common case in any way (i.e., I wouldn't be in favor
>of introducing a whole bunch of layers of template
>metaprogramming tricks to get this to work).
>

I can't imagine why you'd want size_type to be so small either, but the
fact is that the library allows you to do it, and it lists requirements
for the behavior.

>
>But back to your patch, unless it actually addresses this
>problem, we still need a test case for the problem that it
>does attempt to fix.
>

I agree. I was sure this was an actual problem. If it is deemed to not
be an issue, then I'm happy to let it slide.

>
>Martin
>
>


>Martin
>
>

Re: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
>  
> 
> Martin,
> 
> I think that you are right in the case of push_back, or when the string
> to append is short. My last testcase didn't prove anything. This one
> does. If you use the current trunk, this prints '4 aaaa' to the console.
> i.e. appending 20 characters to a buffer with 240 should not get you 4,
> should it?
[...]
> template <class _TypeT>
> class Xallocator
> {
> public:
>     typedef unsigned char       size_type;

I suspect the problem might actually be here. Once you define
size_type to a type with a more generous range the test case
passes. I made this and a few other simplifying changes in
the attached program (it's also possible that I messed
something up in the process ;-)

Martin


RE: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Travis Vitek <tv...@quovadx.com>.
 

Martin,

I think that you are right in the case of push_back, or when the string
to append is short. My last testcase didn't prove anything. This one
does. If you use the current trunk, this prints '4 aaaa' to the console.
i.e. appending 20 characters to a buffer with 240 should not get you 4,
should it?

Travis


#include <string>
#include <stdexcept>
#include <malloc.h>

template <class _TypeT> class
Xallocator;

template <>
class Xallocator<void>
{
public:
    typedef void              value_type;
    typedef value_type*       pointer;
    typedef const value_type* const_pointer;
   
    template <class _TypeU> 
    struct rebind {
        typedef Xallocator<_TypeU> other;
    };    
};

template <class _TypeT>
class Xallocator
{
public:
    typedef unsigned char       size_type;
    typedef signed char         difference_type;
    typedef _TypeT              value_type;
    typedef value_type*         pointer;
    typedef const value_type*   const_pointer;
    typedef value_type&         reference;
    typedef const value_type&   const_reference;

    Xallocator () {
    }

    Xallocator (const Xallocator &) {
    }

    template <class _TypeU> 
    struct rebind {
        typedef Xallocator<_TypeU> other;
    };

    template <class _TypeU>
    Xallocator (const Xallocator<_TypeU>&) {
    }

    template <class _TypeU>
    Xallocator&
    operator= (const Xallocator<_TypeU>&) { 
        return *this; 
    }

    pointer address (reference __x) const {
        return _RWSTD_REINTERPRET_CAST (pointer,
                   &_RWSTD_REINTERPRET_CAST (char&, __x));
    }

    const_pointer address (const_reference __x) const {
        return _RWSTD_REINTERPRET_CAST (const_pointer,
                   &_RWSTD_REINTERPRET_CAST (const char&, __x));
    }

    pointer allocate (size_type __n, Xallocator<void>::const_pointer =
0) {
        return (pointer)::malloc(__n * sizeof (value_type));
    }

    void deallocate (pointer __p, size_type) {
        ::free(__p);
    }

    // 20.4.1.1, p11 - the largest N for which allocate (N) might
succeed
    size_type max_size () const { 
        return 255;
    }

    void construct (pointer __p, const_reference __val) {
        new (__p) value_type(__val);
    }
    
    void destroy (pointer __p) {
        __p->~_TypeT ();
    }
};

typedef std::basic_string<char, std::char_traits<char>, Xallocator<char>
> String;

#include <stdio.h>

int main()
{
    int failed = 0;

    try {
        String a (240, 'a');
        String b (240, 'b');

        // ensure that we will overflow
        assert (a.max_size () < a.size () + 20);

        a.append (b.c_str(), 20);

        printf ("%u %s\n", a.size (), a.c_str ());

        failed += 1;
    }
    catch (const std::length_error&) {
        // should throw
    }
    catch (...) {
        failed += 1;
    }

    return failed;
}

Re: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
>  
> 
> Martin Sebor wrote:
>> Travis Vitek wrote:
>>> If that is the case, then why would we possibly need this 
>>> same code in any of the other methods that are used to extend
>>> the original string?
>> I don't think we do, really. I suspect the main reason why the
>> code is in all other (out-of-line) modifiers is so we can throw
>> the exception from function that is called directly by program
>> rather than from the one that happens to be called from it to
>> do the real work (all roads lead to replace()).
>>
> 
> The problem I see is this...
> 
>     // if you do this calculation without checking for overflow
>     // you may be surprised when __size becomes smaller than
>     // capacity. [240 + 20 = 6]

I agree that this is at least a theoretical problem (I can't
quite imagine a practical use case for size_type being only
8 bits wide). It might be an interesting exercise to change
string (and the other containers) to work correctly even
with size_type this small so long as it doesn't pessimize
the common case in any way (i.e., I wouldn't be in favor
of introducing a whole bunch of layers of template
metaprogramming tricks to get this to work).

But back to your patch, unless it actually addresses this
problem, we still need a test case for the problem that it
does attempt to fix.

Martin


Re: [PATCH] Add overflow checking to basic_string append and push_back

Posted by "mark.g.brown" <ma...@gmail.com>.
Travis Vitek wrote:
>  
> 
> Martin Sebor wrote:
>> Travis Vitek wrote:
>>> If that is the case, then why would we possibly need this 
>>> same code in any of the other methods that are used to extend
>>> the original string?
>> I don't think we do, really. I suspect the main reason why the
>> code is in all other (out-of-line) modifiers is so we can throw
>> the exception from function that is called directly by program
>> rather than from the one that happens to be called from it to
>> do the real work (all roads lead to replace()).
>>
> 
> The problem I see is this...

I'm afraid this is my fault. I honestly didn't think about overflow
when I wrote the patch for push_back. I'm sorry if that caused
a problem! I'll try to to be more careful next time.

-- Mark

> 
>     // if you do this calculation without checking for overflow
>     // you may be surprised when __size becomes smaller than
>     // capacity. [240 + 20 = 6]
>     //
>     const size_type __size = size () + __n;
> 
>     // if we get here and capacity () is 240, but __size is 6
>     // replace() won't be called.
>     if (   capacity () <= __size
>         || size_type (1) < size_type (_C_pref ()->_C_get_ref ()))
>         return replace (size (), size_type (), __s, __n);
> 
>     // and we will copy past the end of _C_data
>     traits_type::copy (_C_data + size (), __s, __n);
> 
>     // then throw a null terminator down
>     traits_type::assign (_C_data [__size], value_type ());
> 
>     // and record the wrong size
>     _C_pref ()->_C_size._C_size = __size;
> 
> With the default std::string/wstring, there isn't really a problem
> because the allocator fails before size_type will overflow, but that
> doesn't mean it isn't a problem.
> 
> Travis
> 
>> I think the test case has some problems but I just saw your
>> update so I'll follow up on it there.
>>
>> Martin
>>
> 


RE: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Travis Vitek <tv...@quovadx.com>.
 

Martin Sebor wrote:
>
>Travis Vitek wrote:
>> 
>> If that is the case, then why would we possibly need this 
>> same code in any of the other methods that are used to extend
>> the original string?
>
>I don't think we do, really. I suspect the main reason why the
>code is in all other (out-of-line) modifiers is so we can throw
>the exception from function that is called directly by program
>rather than from the one that happens to be called from it to
>do the real work (all roads lead to replace()).
>

The problem I see is this...

    // if you do this calculation without checking for overflow
    // you may be surprised when __size becomes smaller than
    // capacity. [240 + 20 = 6]
    //
    const size_type __size = size () + __n;

    // if we get here and capacity () is 240, but __size is 6
    // replace() won't be called.
    if (   capacity () <= __size
        || size_type (1) < size_type (_C_pref ()->_C_get_ref ()))
        return replace (size (), size_type (), __s, __n);

    // and we will copy past the end of _C_data
    traits_type::copy (_C_data + size (), __s, __n);

    // then throw a null terminator down
    traits_type::assign (_C_data [__size], value_type ());

    // and record the wrong size
    _C_pref ()->_C_size._C_size = __size;

With the default std::string/wstring, there isn't really a problem
because the allocator fails before size_type will overflow, but that
doesn't mean it isn't a problem.

Travis

>
>I think the test case has some problems but I just saw your
>update so I'll follow up on it there.
>
>Martin
>

Re: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
[...]
>> The change also seems unnecessary -- when size() equals capacity()
>> we check that it doesn't exceed max_size() before allocating more
>> memory in append(). Otherwise, when size() is less than capacity()
>> (or rather capacity() - 1), there should be no reason to check
>> against max_size() because we know that capacity() must have
>> been below max_size() the last time we reallocated.
> 
> If that is the case, then why would we possibly need this same code in
> any of the other methods that are used to extend the original string?

I don't think we do, really. I suspect the main reason why the
code is in all other (out-of-line) modifiers is so we can throw
the exception from function that is called directly by program
rather than from the one that happens to be called from it to
do the real work (all roads lead to replace()).

I think the test case has some problems but I just saw your
update so I'll follow up on it there.

Martin

RE: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Travis Vitek <tv...@quovadx.com>.
 

Martin Sebor wrote:
>
>Travis Vitek wrote:
>> It appears that recent changes to string have accidentally 
>> removed some overflow checking that used to be in the
>> basic_string::append() and push_back() methods. The following
>> patch adds the checks back in.
>
>Does this fix a test failure? Or some regression? (If the former,
>which test? If the latter, we need a test case :)

This is a regression for which we don't have a testcase.

>
>In any event, adding an if to these two performance sensitive
>functions looks risky from an efficiency POV (we'd definitely
>need to see before and after timings to consider the patch).
>

Yes. I agree.

>
>The change also seems unnecessary -- when size() equals capacity()
>we check that it doesn't exceed max_size() before allocating more
>memory in append(). Otherwise, when size() is less than capacity()
>(or rather capacity() - 1), there should be no reason to check
>against max_size() because we know that capacity() must have
>been below max_size() the last time we reallocated.

If that is the case, then why would we possibly need this same code in
any of the other methods that are used to extend the original string?
Here is a testcase.

#include <string>
#include <stdexcept>
#include <new>

template <class _TypeT> class
Xallocator;

template <>
class Xallocator<void>
{
public:
    typedef void              value_type;
    typedef value_type*       pointer;
    typedef const value_type* const_pointer;
   
    template <class _TypeU> 
    struct rebind {
        typedef Xallocator<_TypeU> other;
    };    
};

template <class _TypeT>
class Xallocator
{
public:
    typedef unsigned char       size_type;
    typedef signed char         difference_type;
    typedef _TypeT              value_type;
    typedef value_type*         pointer;
    typedef const value_type*   const_pointer;
    typedef value_type&         reference;
    typedef const value_type&   const_reference;

    Xallocator () {
    }

    Xallocator (const Xallocator &) {
    }

    template <class _TypeU> 
    struct rebind {
        typedef Xallocator<_TypeU> other;
    };

    template <class _TypeU>
    Xallocator (const Xallocator<_TypeU>&) {
    }

    template <class _TypeU>
    Xallocator&
    operator= (const Xallocator<_TypeU>&) { 
        return *this; 
    }

    pointer address (reference __x) const {
        return _RWSTD_REINTERPRET_CAST (pointer,
                   &_RWSTD_REINTERPRET_CAST (char&, __x));
    }

    const_pointer address (const_reference __x) const {
        return _RWSTD_REINTERPRET_CAST (const_pointer,
                   &_RWSTD_REINTERPRET_CAST (const char&, __x));
    }

    pointer allocate (size_type __n, Xallocator<void>::const_pointer =
0) {
        return (pointer)::operator new (__n * sizeof (value_type));
    }

    void deallocate (pointer __p, size_type) {
        ::operator delete (__p);
    }

    // 20.4.1.1, p11 - the largest N for which allocate (N) might
succeed
    size_type max_size () const { 
        return 255;
    }

    void construct (pointer __p, const_reference __val) {
        new (__p) value_type(__val);
    }
    
    void destroy (pointer __p) {
        __p->~_TypeT ();
    }
};

typedef std::basic_string<char, std::char_traits<char>, Xallocator<char>
> String;

static void test_append_1()
{
    const String x(1, 'x');

    String a;
    for (int n = 0; n < 1024; ++n)
        a.append(x);
}

static void test_append_2()
{
    const String x(1, 'x');

    String a;
    for (int n = 0; n < 1024; ++n)
        a.append(x, 0, 1);
}

static void test_append_3()
{
    String a;
    for (int n = 0; n < 1024; ++n)
        a.append("x", 1);
}

static void test_append_4()
{
    String a;
    for (int n = 0; n < 1024; ++n)
        a.append("x");
}

static void test_append_5()
{
    static const char x[] = "x";

    String a;
    for (int n = 0; n < 1024; ++n)
        a.append(x, x+1);
}

static void test_push_back()
{
    String a;
    
    // this should throw, but i get heap corruption
    for (int n = 0; n < 1024; ++n)
        a.push_back ('a');
}


int main ()
{
    int failed = 0;

    void (*tests[])() = {
        &test_append_1,
        &test_append_2,
        &test_append_3,
        &test_append_4,
        &test_append_5,
        &test_push_back,
        0 // sentinel
    };

    for (int n = 0; tests[n]; ++n)
    {
        try {
            tests[n]();

            failed += 1;
        }
        catch (const std::length_error&) {
            // expected
        }
        catch (...) {
            failed += 1;
        }
    }

    return failed;
}


Re: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
> It appears that recent changes to string have accidentally removed some
> overflow checking that used to be in the basic_string::append() and
> push_back() methods. The following patch adds the checks back in.

Does this fix a test failure? Or some regression? (If the former,
which test? If the latter, we need a test case :)

In any event, adding an if to these two performance sensitive
functions looks risky from an efficiency POV (we'd definitely
need to see before and after timings to consider the patch).

The change also seems unnecessary -- when size() equals capacity()
we check that it doesn't exceed max_size() before allocating more
memory in append(). Otherwise, when size() is less than capacity()
(or rather capacity() - 1), there should be no reason to check
against max_size() because we know that capacity() must have
been below max_size() the last time we reallocated.

Martin

> 
> Travis
> 
> 
> 2007-09-20  Travis Vitek  <vi...@roguewave.com>
> 
> 	* string (append): add integer overflow check
> 	(push_back): Same
> 
> ===================================================================
> --- string	(revision 576541)
> +++ string	(working copy)
> @@ -1088,6 +1088,11 @@
>  inline void basic_string<_CharT, _Traits, _Allocator>::
>  push_back (value_type __c)
>  {
> +    _RWSTD_REQUIRES (size () <= max_size () - 1,
> +                     (_RWSTD_ERROR_LENGTH_ERROR,
> +                      _RWSTD_FUNC ("basic_string::append(value_type)"),
> +                      size (), max_size () - 1));
> +
>      const size_type __size = size () + 1;
>  
>      if (   capacity () < __size
> @@ -1095,7 +1100,6 @@
>          append (1, __c);
>      else {
>          traits_type::assign (_C_data [size ()], __c);
> -        // append the terminating NUL character
>          traits_type::assign (_C_data [__size], value_type ());
>          _C_pref ()->_C_size._C_size = __size;
>      }
> @@ -1196,6 +1200,12 @@
>  basic_string<_CharT, _Traits, _Allocator>::
>  append (const_pointer __s, size_type __n)
>  {
> +    _RWSTD_REQUIRES (size () <= max_size () - __n,
> +                     (_RWSTD_ERROR_LENGTH_ERROR,
> +                      _RWSTD_FUNC
> ("basic_string::append(const_pointer,"
> +                                   " size_type)"),
> +                      size (), max_size () - __n));
> +
>      const size_type __newsize = size () + __n;
>  
>      if (   capacity () <= __newsize


RE: [PATCH] Add overflow checking to basic_string append and push_back

Posted by Travis Vitek <tv...@quovadx.com>.
 

Travis Vitek wrote:
>
>It appears that recent changes to string have accidentally removed some
>overflow checking that used to be in the basic_string::append() and
>push_back() methods. The following patch adds the checks back in.
>
>Travis
>

Lets try that again. This one has the correct method name for the
push_back() _RWSTD_REQUIRES.

Travis

2007-09-20  Travis Vitek  <vi...@roguewave.com>

	* string (append): add integer overflow check
	(push_back): Same

===================================================================
--- string	(revision 576541)
+++ string	(working copy)
@@ -1088,6 +1088,11 @@
 inline void basic_string<_CharT, _Traits, _Allocator>::
 push_back (value_type __c)
 {
+    _RWSTD_REQUIRES (size () <= max_size () - 1,
+                     (_RWSTD_ERROR_LENGTH_ERROR,
+                      _RWSTD_FUNC
("basic_string::push_back(value_type)"),
+                      size (), max_size () - 1));
+
     const size_type __size = size () + 1;
 
     if (   capacity () < __size
@@ -1095,7 +1100,6 @@
         append (1, __c);
     else {
         traits_type::assign (_C_data [size ()], __c);
-        // append the terminating NUL character
         traits_type::assign (_C_data [__size], value_type ());
         _C_pref ()->_C_size._C_size = __size;
     }
@@ -1196,6 +1200,12 @@
 basic_string<_CharT, _Traits, _Allocator>::
 append (const_pointer __s, size_type __n)
 {
+    _RWSTD_REQUIRES (size () <= max_size () - __n,
+                     (_RWSTD_ERROR_LENGTH_ERROR,
+                      _RWSTD_FUNC
("basic_string::append(const_pointer,"
+                                   " size_type)"),
+                      size (), max_size () - __n));
+
     const size_type __newsize = size () + __n;
 
     if (   capacity () <= __newsize