Modify

Ticket #3166 (closed Bugs: fixed)

Opened 5 years ago

Last modified 5 years ago

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

Change History

comment:1 Changed 5 years ago by anonymous

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

comment:2 Changed 5 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 5 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 5 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 5 years ago by igaztanaga

Fixed for Boost 1.40

comment:6 Changed 5 years ago by igaztanaga

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

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
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.