Opened 13 years ago

Closed 13 years ago

#3166 closed Bugs (fixed)

Possible Bug in Boost.Interprocess vectorstream

Reported by: chsalvia@… Owned by: Ion Gaztañaga
Milestone: Boost 1.40.0 Component: interprocess
Version: Boost 1.39.0 Severity: Problem
Keywords: Cc:

Description

There is possibly a bug in the vectorstream class found in the Boost Interprocess library. It seems the internal pointer mp_high_water doesn't get updated every time new data is inserted into the stream via xsputn, which causes problems if you call seekp on a stream.

The following code demonstrates the problem:

using namespace std;
using namespace boost::interprocess;

typedef basic_ovectorstream<std::vector<char>, std::char_traits<char> > vecstream;
vecstream vs;

vs << "AAAABBBB";

vs.seekp(0);

// Output the contents of the internal vector
//
const std::vector<char>& vec = vs.vector();
for (int i = 0; i < vec.size(); ++i) cout << vec[i];
cout << endl;

This outputs: AAAAB

When it should output: AAAABBBB

Change History (6)

comment:1 by anonymous, 13 years ago

Component: Noneinterprocess
Owner: set to Ion Gaztañaga

comment:2 by anonymous, 13 years ago

This could be resolved by overloading xsputn in the vectorstream class in order to update the internal high water mark pointer after calling std::basic_streambuf<char_type, traits>::xsputn.

virtual std::streamsize xsputn(const char_type* s, std::streamsize n)
{
	std::streamsize ret = base_type::xsputn(s, n);
	if (mp_high_water < base_t::pptr()) mp_high_water = base_t::pptr();
	return ret;	
}

comment:3 by chsalvia@…, 13 years ago

Essentially, this bug happens because the vector stream class has a member function vector(), which returns a const reference to the internal vector. But, if the the vectorstream is an output stream, a call to vector() also resizes the vector:

 //!Returns a const reference to the internal vector.
   //!Does not throw.
   const vector_type &vector() const 
   {  
      if (this->m_mode & std::ios_base::out){
         if (mp_high_water < base_t::pptr()){
            //Restore the vector's size if necessary
            mp_high_water = base_t::pptr();
         }
         m_vect.resize(mp_high_water - (m_vect.size() ? &m_vect[0] : 0));
         const_cast<basic_vectorbuf * const>(this)->initialize_pointers();
      }
      return m_vect; 
   }

Before resizing, the mp_high_water mark is set to the current position in the output sequence if it is less than pptr(). But, if a previous call to basic_vectorbuf::seekoff sets the stream position to 0, then the mp_high_water mark will not be changed, and the vector will be incorrectly resized.

comment:4 by chsalvia@…, 13 years ago

Actually, the best way to fix this is probably to update the high water mark when a call to seekoff() is made. That way, overloading xsputn is unnecessary, and sputc will work properly as well.

In basic_vectorbuf<CharVector, Traits>::seekoff(), the following line could be added to fix the problem:

if (mp_high_water < base_type::pptr()) mp_high_water = base_type::pptr();

comment:5 by Ion Gaztañaga, 13 years ago

Fixed for Boost 1.40

comment:6 by Ion Gaztañaga, 13 years ago

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.