summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarshall Clow <mclow.lists@gmail.com>2017-09-12 15:00:43 +0000
committerMarshall Clow <mclow.lists@gmail.com>2017-09-12 15:00:43 +0000
commit29149d3e3565813dcf8b9adc895a6a39eeccdd09 (patch)
tree69559651ab6f3567b5404f1dfcf63a9b467b79f9
parent60f8ad1b1dbfa6673919bbf3e7e629997224651d (diff)
Make pbump (internally) handle sizes bigger than MAX_INT. Fixes PR#33725 - thanks to Jonathan Wakely for the report
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@313031 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/fstream8
-rw-r--r--include/locale2
-rw-r--r--include/sstream20
-rw-r--r--include/streambuf3
-rw-r--r--src/strstream.cpp6
-rw-r--r--test/std/input.output/stream.buffers/streambuf/streambuf.protected/streambuf.put.area/pbump2gig.pass.cpp41
6 files changed, 66 insertions, 14 deletions
diff --git a/include/fstream b/include/fstream
index ffd569839..f57908c8d 100644
--- a/include/fstream
+++ b/include/fstream
@@ -315,7 +315,7 @@ basic_filebuf<_CharT, _Traits>::basic_filebuf(basic_filebuf&& __rhs)
else
this->setp((char_type*)__extbuf_,
(char_type*)__extbuf_ + (__rhs. epptr() - __rhs.pbase()));
- this->pbump(__rhs. pptr() - __rhs.pbase());
+ this->__pbump(__rhs. pptr() - __rhs.pbase());
}
else if (__rhs.eback())
{
@@ -434,7 +434,7 @@ basic_filebuf<_CharT, _Traits>::swap(basic_filebuf& __rhs)
ptrdiff_t __e = this->epptr() - this->pbase();
this->setp((char_type*)__extbuf_min_,
(char_type*)__extbuf_min_ + __e);
- this->pbump(__n);
+ this->__pbump(__n);
}
if (__rhs.eback() == (char_type*)__extbuf_min_)
{
@@ -450,7 +450,7 @@ basic_filebuf<_CharT, _Traits>::swap(basic_filebuf& __rhs)
ptrdiff_t __e = __rhs.epptr() - __rhs.pbase();
__rhs.setp((char_type*)__rhs.__extbuf_min_,
(char_type*)__rhs.__extbuf_min_ + __e);
- __rhs.pbump(__n);
+ __rhs.__pbump(__n);
}
}
@@ -724,7 +724,7 @@ basic_filebuf<_CharT, _Traits>::overflow(int_type __c)
if (__r == codecvt_base::partial)
{
this->setp(const_cast<char_type*>(__e), this->pptr());
- this->pbump(this->epptr() - this->pbase());
+ this->__pbump(this->epptr() - this->pbase());
}
}
else
diff --git a/include/locale b/include/locale
index d30d950c7..a86645d2c 100644
--- a/include/locale
+++ b/include/locale
@@ -4110,7 +4110,7 @@ wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
if (__r == codecvt_base::partial)
{
this->setp(const_cast<char_type *>(__e), this->pptr());
- this->pbump(this->epptr() - this->pbase());
+ this->__pbump(this->epptr() - this->pbase());
}
}
else
diff --git a/include/sstream b/include/sstream
index fe65fd7db..31cb37a1e 100644
--- a/include/sstream
+++ b/include/sstream
@@ -289,7 +289,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::basic_stringbuf(basic_stringbuf&&
if (__bout != -1)
{
this->setp(__p + __bout, __p + __eout);
- this->pbump(__nout);
+ this->__pbump(__nout);
}
__hm_ = __hm == -1 ? nullptr : __p + __hm;
__p = const_cast<char_type*>(__rhs.__str_.data());
@@ -332,7 +332,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::operator=(basic_stringbuf&& __rhs)
if (__bout != -1)
{
this->setp(__p + __bout, __p + __eout);
- this->pbump(__nout);
+ this->__pbump(__nout);
}
else
this->setp(nullptr, nullptr);
@@ -403,7 +403,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::swap(basic_stringbuf& __rhs)
if (__rbout != -1)
{
this->setp(__p + __rbout, __p + __reout);
- this->pbump(__rnout);
+ this->__pbump(__rnout);
}
else
this->setp(nullptr, nullptr);
@@ -416,7 +416,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::swap(basic_stringbuf& __rhs)
if (__lbout != -1)
{
__rhs.setp(__p + __lbout, __p + __leout);
- __rhs.pbump(__lnout);
+ __rhs.__pbump(__lnout);
}
else
__rhs.setp(nullptr, nullptr);
@@ -471,7 +471,15 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::str(const string_type& __s)
this->setp(const_cast<char_type*>(__str_.data()),
const_cast<char_type*>(__str_.data()) + __str_.size());
if (__mode_ & (ios_base::app | ios_base::ate))
- this->pbump(__sz);
+ {
+ while (__sz > INT_MAX)
+ {
+ this->pbump(INT_MAX);
+ __sz -= INT_MAX;
+ }
+ if (__sz > 0)
+ this->pbump(__sz);
+ }
}
}
@@ -536,7 +544,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::overflow(int_type __c)
__str_.resize(__str_.capacity());
char_type* __p = const_cast<char_type*>(__str_.data());
this->setp(__p, __p + __str_.size());
- this->pbump(__nout);
+ this->__pbump(__nout);
__hm_ = this->pbase() + __hm;
#ifndef _LIBCPP_NO_EXCEPTIONS
}
diff --git a/include/streambuf b/include/streambuf
index f6182d64f..ea64f5780 100644
--- a/include/streambuf
+++ b/include/streambuf
@@ -255,6 +255,9 @@ protected:
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
void pbump(int __n) { __nout_ += __n; }
+ _LIBCPP_ALWAYS_INLINE
+ void __pbump(streamsize __n) { __nout_ += __n; }
+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
void setp(char_type* __pbeg, char_type* __pend) {
__bout_ = __nout_ = __pbeg;
diff --git a/src/strstream.cpp b/src/strstream.cpp
index 01523cf45..8b8521f76 100644
--- a/src/strstream.cpp
+++ b/src/strstream.cpp
@@ -186,7 +186,7 @@ strstreambuf::overflow(int_type __c)
}
setg(buf, buf + ninp, buf + einp);
setp(buf + einp, buf + new_size);
- pbump(static_cast<int>(nout));
+ __pbump(nout);
__strmode_ |= __allocated;
}
*pptr() = static_cast<char>(__c);
@@ -282,7 +282,7 @@ strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmod
// min(pbase, newpos), newpos, epptr()
__off = epptr() - newpos;
setp(min(pbase(), newpos), epptr());
- pbump(static_cast<int>((epptr() - pbase()) - __off));
+ __pbump((epptr() - pbase()) - __off);
}
__p = newoff;
}
@@ -312,7 +312,7 @@ strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
// min(pbase, newpos), newpos, epptr()
off_type temp = epptr() - newpos;
setp(min(pbase(), newpos), epptr());
- pbump(static_cast<int>((epptr() - pbase()) - temp));
+ __pbump((epptr() - pbase()) - temp);
}
__p = newoff;
}
diff --git a/test/std/input.output/stream.buffers/streambuf/streambuf.protected/streambuf.put.area/pbump2gig.pass.cpp b/test/std/input.output/stream.buffers/streambuf/streambuf.protected/streambuf.put.area/pbump2gig.pass.cpp
new file mode 100644
index 000000000..a581f881d
--- /dev/null
+++ b/test/std/input.output/stream.buffers/streambuf/streambuf.protected/streambuf.put.area/pbump2gig.pass.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <streambuf>
+
+// template <class charT, class traits = char_traits<charT> >
+// class basic_streambuf;
+
+// void pbump(int n);
+
+#include <sstream>
+#include <cassert>
+#include "test_macros.h"
+
+struct SB : std::stringbuf
+{
+ SB() : std::stringbuf(std::ios::ate|std::ios::out) { }
+ const char* pubpbase() const { return pbase(); }
+ const char* pubpptr() const { return pptr(); }
+};
+
+int main()
+{
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+#endif
+ std::string str(2147483648, 'a');
+ SB sb;
+ sb.str(str);
+ assert(sb.pubpbase() <= sb.pubpptr());
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ }
+ catch (const std::bad_alloc &) {}
+#endif
+}