From 916bdde163142a9d88d4ff352bc8503ca535d794 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Wed, 12 Nov 2025 22:46:29 +0000 Subject: [PATCH 1/2] [libcxx] Fix xsgetn in basic_filebuf The optimized version of xsgetn for basic_filebuf added in #165223 has an issue where if the reads come from both the buffer and the filesystem it returns the wrong number of characters. This patch should address the issue. --- libcxx/include/fstream | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libcxx/include/fstream b/libcxx/include/fstream index b07ca636094af..ef670728adec4 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -310,13 +310,19 @@ protected: _LIBCPP_HIDE_FROM_ABI_VIRTUAL streamsize xsgetn(char_type* __str, streamsize __len) override { if (__always_noconv_) { - const streamsize __n = std::min(this->egptr() - this->gptr(), __len); + const streamsize __n = std::min( this->egptr() - this->gptr(), __len); if (__n != 0) { traits_type::copy(__str, this->gptr(), __n); this->__gbump_ptrdiff(__n); } - if (__len - __n >= this->egptr() - this->eback()) - return std::fread(__str + __n, sizeof(char_type), __len - __n, __file_); + const streamsize __remainder = __len - __n; + const streamsize __buffer_space = this->egptr() - this->eback(); + + if (__remainder >= __buffer_space) + return std::fread(__str + __n, sizeof(char_type), __remainder, __file_) + __n; + else if( __remainder > 0) + return basic_streambuf<_CharT, _Traits>::xsgetn(__str + __n, __remainder) + __n; + return __n; } return basic_streambuf<_CharT, _Traits>::xsgetn(__str, __len); } From 458b6569cc6788a19528b451ad472c561ef0a3cd Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Wed, 12 Nov 2025 22:53:20 +0000 Subject: [PATCH 2/2] format --- libcxx/include/fstream | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcxx/include/fstream b/libcxx/include/fstream index ef670728adec4..90e35740c17cf 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -310,17 +310,17 @@ protected: _LIBCPP_HIDE_FROM_ABI_VIRTUAL streamsize xsgetn(char_type* __str, streamsize __len) override { if (__always_noconv_) { - const streamsize __n = std::min( this->egptr() - this->gptr(), __len); + const streamsize __n = std::min(this->egptr() - this->gptr(), __len); if (__n != 0) { traits_type::copy(__str, this->gptr(), __n); this->__gbump_ptrdiff(__n); } - const streamsize __remainder = __len - __n; + const streamsize __remainder = __len - __n; const streamsize __buffer_space = this->egptr() - this->eback(); if (__remainder >= __buffer_space) return std::fread(__str + __n, sizeof(char_type), __remainder, __file_) + __n; - else if( __remainder > 0) + else if (__remainder > 0) return basic_streambuf<_CharT, _Traits>::xsgetn(__str + __n, __remainder) + __n; return __n; }