From 53aed4759b33e33614e0f4e321bc1ef764b6d5b6 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Wed, 17 May 2023 09:16:54 -0700 Subject: [libcxx] Fix crash in std::stringstream with payload >= INT_MAX 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. Reviewed By: #libc, ldionne, Mordante Spies: arichardson, Mordante, philnik, ldionne, libcxx-commits, mikhail.ramalho Differential Revision: https://reviews.llvm.org/D146294 --- libcxx/include/sstream | 2 +- .../stringstream.members/gcount.pass.cpp | 41 ++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 libcxx/test/std/input.output/string.streams/stringstream.members/gcount.pass.cpp (limited to 'libcxx') diff --git a/libcxx/include/sstream b/libcxx/include/sstream index 6dd581e30cb4..26c899215322 100644 --- a/libcxx/include/sstream +++ b/libcxx/include/sstream @@ -646,7 +646,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); } diff --git a/libcxx/test/std/input.output/string.streams/stringstream.members/gcount.pass.cpp b/libcxx/test/std/input.output/string.streams/stringstream.members/gcount.pass.cpp new file mode 100644 index 000000000000..7dbd68ec4373 --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/stringstream.members/gcount.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// All 32 bit arches that CI has: +// +// UNSUPPORTED: target=powerpc-ibm-aix +// UNSUPPORTED: target=armv7l-linux-gnueabihf +// UNSUPPORTED: target=armv8l-linux-gnueabihf +// UNSUPPORTED: target=i686-w64-windows-gnu + +// Test that tellp() does not break the stringstream after INT_MAX, due to use +// of pbump() that accept int. + +#include +#include +#include +#include + +int main(int, char**) { + std::stringstream ss; + std::string payload(INT_MAX - 1, '\0'); + + ss.write(payload.data(), payload.size()); + assert(ss.tellp() == INT_MAX - 1); + + ss.write("a", 1); + assert(ss.tellp() == INT_MAX); + + ss.write("b", 1); + assert(ss.tellp() == INT_MAX + 1ULL); + // it fails only after previous tellp() corrupts the internal field with int + // overflow + assert(ss.tellp() == INT_MAX + 1ULL); + + return 0; +} -- cgit v1.2.1