[libcxx] Make std::basic_istream::get 0-terminate input array in case of error.
It covers the cases when the sentry object returns false and when an exception was thrown. Corresponding standard paragraph is C++14 [istream.unformatted]p9: [...] In any case, if n is greater than zero it then stores a null character into the next successive location of the array. rdar://problem/35566567 Reviewers: EricWF, mclow.lists Reviewed By: mclow.lists Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D40677 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@322326 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -960,7 +960,6 @@ basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n, char_type __
|
|||||||
++__gc_;
|
++__gc_;
|
||||||
this->rdbuf()->sbumpc();
|
this->rdbuf()->sbumpc();
|
||||||
}
|
}
|
||||||
*__s = char_type();
|
|
||||||
if (__gc_ == 0)
|
if (__gc_ == 0)
|
||||||
__err |= ios_base::failbit;
|
__err |= ios_base::failbit;
|
||||||
this->setstate(__err);
|
this->setstate(__err);
|
||||||
@@ -968,10 +967,14 @@ basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n, char_type __
|
|||||||
else
|
else
|
||||||
this->setstate(ios_base::failbit);
|
this->setstate(ios_base::failbit);
|
||||||
}
|
}
|
||||||
|
if (__n > 0)
|
||||||
|
*__s = char_type();
|
||||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
if (__n > 0)
|
||||||
|
*__s = char_type();
|
||||||
this->__set_badbit_and_consider_rethrow();
|
this->__set_badbit_and_consider_rethrow();
|
||||||
}
|
}
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
|
|||||||
@@ -7,6 +7,14 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.13
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.12
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.11
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.10
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.9
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.8
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.7
|
||||||
|
|
||||||
// <istream>
|
// <istream>
|
||||||
|
|
||||||
// basic_istream<charT,traits>& get(char_type* s, streamsize n);
|
// basic_istream<charT,traits>& get(char_type* s, streamsize n);
|
||||||
@@ -14,6 +22,8 @@
|
|||||||
#include <istream>
|
#include <istream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
template <class CharT>
|
template <class CharT>
|
||||||
struct testbuf
|
struct testbuf
|
||||||
: public std::basic_streambuf<CharT>
|
: public std::basic_streambuf<CharT>
|
||||||
@@ -67,7 +77,33 @@ int main()
|
|||||||
assert(!is.fail());
|
assert(!is.fail());
|
||||||
assert(std::string(s) == " ");
|
assert(std::string(s) == " ");
|
||||||
assert(is.gcount() == 1);
|
assert(is.gcount() == 1);
|
||||||
|
// Check that even in error case the buffer is properly 0-terminated.
|
||||||
|
is.get(s, 5);
|
||||||
|
assert( is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::string(s) == "");
|
||||||
|
assert(is.gcount() == 0);
|
||||||
}
|
}
|
||||||
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
|
{
|
||||||
|
testbuf<char> sb(" ");
|
||||||
|
std::istream is(&sb);
|
||||||
|
char s[5] = "test";
|
||||||
|
is.exceptions(std::istream::eofbit | std::istream::badbit);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
is.get(s, 5);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::ios_base::failure&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
assert( is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::string(s) == " ");
|
||||||
|
assert(is.gcount() == 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
testbuf<wchar_t> sb(L" \n \n ");
|
testbuf<wchar_t> sb(L" \n \n ");
|
||||||
std::wistream is(&sb);
|
std::wistream is(&sb);
|
||||||
@@ -95,5 +131,31 @@ int main()
|
|||||||
assert(!is.fail());
|
assert(!is.fail());
|
||||||
assert(std::wstring(s) == L" ");
|
assert(std::wstring(s) == L" ");
|
||||||
assert(is.gcount() == 1);
|
assert(is.gcount() == 1);
|
||||||
|
// Check that even in error case the buffer is properly 0-terminated.
|
||||||
|
is.get(s, 5);
|
||||||
|
assert( is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::wstring(s) == L"");
|
||||||
|
assert(is.gcount() == 0);
|
||||||
}
|
}
|
||||||
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
|
{
|
||||||
|
testbuf<wchar_t> sb(L" ");
|
||||||
|
std::wistream is(&sb);
|
||||||
|
wchar_t s[5] = L"test";
|
||||||
|
is.exceptions(std::wistream::eofbit | std::wistream::badbit);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
is.get(s, 5);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::ios_base::failure&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
assert( is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::wstring(s) == L" ");
|
||||||
|
assert(is.gcount() == 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,14 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.13
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.12
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.11
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.10
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.9
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.8
|
||||||
|
// XFAIL: with_system_cxx_lib=macosx10.7
|
||||||
|
|
||||||
// <istream>
|
// <istream>
|
||||||
|
|
||||||
// basic_istream<charT,traits>& get(char_type* s, streamsize n, char_type delim);
|
// basic_istream<charT,traits>& get(char_type* s, streamsize n, char_type delim);
|
||||||
@@ -14,6 +22,8 @@
|
|||||||
#include <istream>
|
#include <istream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
template <class CharT>
|
template <class CharT>
|
||||||
struct testbuf
|
struct testbuf
|
||||||
: public std::basic_streambuf<CharT>
|
: public std::basic_streambuf<CharT>
|
||||||
@@ -67,7 +77,33 @@ int main()
|
|||||||
assert(!is.fail());
|
assert(!is.fail());
|
||||||
assert(std::string(s) == " ");
|
assert(std::string(s) == " ");
|
||||||
assert(is.gcount() == 1);
|
assert(is.gcount() == 1);
|
||||||
|
// Check that even in error case the buffer is properly 0-terminated.
|
||||||
|
is.get(s, 5, '*');
|
||||||
|
assert( is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::string(s) == "");
|
||||||
|
assert(is.gcount() == 0);
|
||||||
}
|
}
|
||||||
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
|
{
|
||||||
|
testbuf<char> sb(" ");
|
||||||
|
std::istream is(&sb);
|
||||||
|
char s[5] = "test";
|
||||||
|
is.exceptions(std::istream::eofbit | std::istream::badbit);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
is.get(s, 5, '*');
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::ios_base::failure&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
assert( is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::string(s) == " ");
|
||||||
|
assert(is.gcount() == 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
testbuf<wchar_t> sb(L" * * ");
|
testbuf<wchar_t> sb(L" * * ");
|
||||||
std::wistream is(&sb);
|
std::wistream is(&sb);
|
||||||
@@ -95,5 +131,31 @@ int main()
|
|||||||
assert(!is.fail());
|
assert(!is.fail());
|
||||||
assert(std::wstring(s) == L" ");
|
assert(std::wstring(s) == L" ");
|
||||||
assert(is.gcount() == 1);
|
assert(is.gcount() == 1);
|
||||||
|
// Check that even in error case the buffer is properly 0-terminated.
|
||||||
|
is.get(s, 5, L'*');
|
||||||
|
assert( is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::wstring(s) == L"");
|
||||||
|
assert(is.gcount() == 0);
|
||||||
}
|
}
|
||||||
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
|
{
|
||||||
|
testbuf<wchar_t> sb(L" ");
|
||||||
|
std::wistream is(&sb);
|
||||||
|
wchar_t s[5] = L"test";
|
||||||
|
is.exceptions(std::wistream::eofbit | std::wistream::badbit);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
is.get(s, 5, L'*');
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (std::ios_base::failure&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
assert( is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::wstring(s) == L" ");
|
||||||
|
assert(is.gcount() == 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user