From 12ecde40a2e5069507f2e8733f597160d80606bb Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Mon, 9 Jan 2023 13:55:18 -0500 Subject: [PATCH] vectorstream: support file sizes larger than INT_MAX File sizes larger than INT_MAX cause segmentation faults, due to the use of `pbump/gbump`, which only support `int` increments. Rewrite `int`-based offset adjustments to use streamoff offsets instead. Fixes #190. --- .../interprocess/streams/vectorstream.hpp | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/include/boost/interprocess/streams/vectorstream.hpp b/include/boost/interprocess/streams/vectorstream.hpp index 36ed3915..e4845a01 100644 --- a/include/boost/interprocess/streams/vectorstream.hpp +++ b/include/boost/interprocess/streams/vectorstream.hpp @@ -52,6 +52,7 @@ #include #include #include // char traits +#include // INT_MAX #include // ptrdiff_t #include #include @@ -138,9 +139,9 @@ class basic_vectorbuf if(m_vect.size() > high_pos){ m_vect.resize(high_pos); //But we must update end write pointer because vector size is now shorter - int old_pos = (int)(base_t::pptr() - base_t::pbase()); + off_type old_pos = base_t::pptr() - base_t::pbase(); const_cast(this)->base_t::setp(old_ptr, old_ptr + high_pos); - const_cast(this)->base_t::pbump(old_pos); + const_cast(this)->pbump(old_pos); } } return m_vect; @@ -152,14 +153,14 @@ class basic_vectorbuf void reserve(typename vector_type::size_type size) { if (this->m_mode & std::ios_base::out && size > m_vect.size()){ - typename vector_type::difference_type write_pos = base_t::pptr() - base_t::pbase(); - typename vector_type::difference_type read_pos = base_t::gptr() - base_t::eback(); + off_type write_pos = base_t::pptr() - base_t::pbase(); + off_type read_pos = base_t::gptr() - base_t::eback(); //Now update pointer data m_vect.reserve(size); this->initialize_pointers(); - base_t::pbump((int)write_pos); + this->pbump(write_pos); if(this->m_mode & std::ios_base::in){ - base_t::gbump((int)read_pos); + base_t::setg(base_t::eback(), base_t::eback() + read_pos, base_t::egptr()); } } } @@ -189,7 +190,7 @@ class basic_vectorbuf // The initial write position is the beginning of the vector. if(m_mode & std::ios_base::out){ //First get real size - int real_size = (int)m_vect.size(); + off_type real_size = m_vect.size(); //Then maximize size for high watermarking m_vect.resize(m_vect.capacity()); BOOST_ASSERT(m_vect.size() == m_vect.capacity()); @@ -208,11 +209,21 @@ class basic_vectorbuf this->setg(p, p, p + real_size); } if (m_mode & (std::ios_base::app | std::ios_base::ate)){ - base_t::pbump((int)real_size); + this->pbump(real_size); } } } + // LWG255-inspired variant of base_t::pbump that takes a streamoff instead of an int. + void pbump(off_type delta) { + if (delta > INT_MAX) { + for (off_type d = delta / INT_MAX; d > 0; d--) + base_t::pbump(INT_MAX); + delta %= INT_MAX; + } + base_t::pbump((int)delta); + } + protected: virtual int_type underflow() BOOST_OVERRIDE { @@ -277,7 +288,7 @@ class basic_vectorbuf if (m_mode & std::ios_base::in) base_t::setg(p, p + (base_t::gptr() - base_t::eback()), mp_high_water); //Update write position to the old position + 1 - base_t::pbump((int)new_outpos); + this->pbump((off_type)new_outpos); return c; } else // c is EOF, so we don't have to do anything @@ -351,7 +362,7 @@ class basic_vectorbuf base_t::setg(base_t::eback(), base_t::eback() + newoff, base_t::egptr()); if (out){ base_t::setp(base_t::pbase(), base_t::epptr()); - base_t::pbump(static_cast(newoff)); + this->pbump(newoff); } return pos_type(newoff); }