Modify

Opened 8 years ago

Closed 8 years ago

#3166 closed Bugs (fixed)

Possible Bug in Boost.Interprocess vectorstream

Reported by: chsalvia@… Owned by: igaztanaga
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

Attachments (0)

Change History (6)

comment:1 Changed 8 years ago by anonymous

  • Component changed from None to interprocess
  • Owner set to igaztanaga

comment:2 Changed 8 years ago by anonymous

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 Changed 8 years ago by chsalvia@…

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 Changed 8 years ago by chsalvia@…

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 Changed 8 years ago by igaztanaga

Fixed for Boost 1.40

comment:6 Changed 8 years ago by igaztanaga

  • Resolution set to fixed
  • Status changed from new to closed

Add Comment

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain igaztanaga.
The resolution will be deleted. Next status will be 'reopened'.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.