Skip to content

Commit

Permalink
[libcxx] Fix crash in std::stringstream with payload >= INT_MAX
Browse files Browse the repository at this point in the history
stringstream does works for payload > INT_MAX, however
stringstream::gcount() can break the internal field (__nout_) and this
breaks the stringstream itself, and so the program will crash.

Fix this, by using __pbump(streamsize) over pbump(int)

Note, libstdc++ does not have this bug.

Signed-off-by: Azat Khuzhin <[email protected]>
Differential Revision: https://reviews.llvm.org/D146294
  • Loading branch information
azat committed Mar 20, 2023
1 parent d80af31 commit 294c977
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
10 changes: 2 additions & 8 deletions libcxx/include/sstream
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::str(const string_type& __s)
const_cast<char_type*>(__str_.data()) + __str_.size());
if (__mode_ & (ios_base::app | ios_base::ate))
{
while (__sz > INT_MAX)
{
this->pbump(INT_MAX);
__sz -= INT_MAX;
}
if (__sz > 0)
this->pbump(__sz);
this->__pbump(__sz);
}
}
}
Expand Down Expand Up @@ -614,7 +608,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::seekoff(off_type __off,
if (__wch & ios_base::out)
{
this->setp(this->pbase(), this->epptr());
this->pbump(__noff);
this->__pbump(__noff);
}
return pos_type(__noff);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// <sstream>

// Test that tellp() does not break the stringstream after INT_MAX, due to use
// of pbump() that accept int.

#include <string>
#include <sstream>
#include <cassert>

int main(int, char**) {
#if __SIZE_WIDTH__ == 64
std::stringstream ss;
std::string payload(1 << 20, 'A');

for (size_t i = 0; i < (2ULL << 30) - payload.size(); i += payload.size()) {
assert(ss.tellp() != -1);
ss.write(payload.data(), payload.size());
}

assert(ss.tellp() != -1);
ss.write(payload.data(), payload.size());

assert(ss.tellp() != -1);
ss.write(payload.data(), payload.size());
#endif

return 0;
}

0 comments on commit 294c977

Please sign in to comment.