[libc++] Implement P0487R1 - Fixing operator>>(basic_istream&, CharT*)
Summary: Avoid buffer overflow by replacing the pointer interface with an array reference interface in C++2a. Tentatively ready on Batavia2018. https://wg21.link/lwg2499 https://wg21.link/p0487 Reviewers: mclow.lists, ldionne, EricWF Reviewed By: ldionne Subscribers: libcxx-commits, cfe-commits, christof Differential Revision: https://reviews.llvm.org/D51268 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@347377 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -517,8 +517,9 @@ basic_istream<_CharT, _Traits>::operator>>(int& __n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class _CharT, class _Traits>
|
template<class _CharT, class _Traits>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
basic_istream<_CharT, _Traits>&
|
basic_istream<_CharT, _Traits>&
|
||||||
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
__input_c_string(basic_istream<_CharT, _Traits>& __is, _CharT* __p, size_t __n)
|
||||||
{
|
{
|
||||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||||
try
|
try
|
||||||
@@ -527,13 +528,10 @@ operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
|||||||
typename basic_istream<_CharT, _Traits>::sentry __sen(__is);
|
typename basic_istream<_CharT, _Traits>::sentry __sen(__is);
|
||||||
if (__sen)
|
if (__sen)
|
||||||
{
|
{
|
||||||
streamsize __n = __is.width();
|
auto __s = __p;
|
||||||
if (__n <= 0)
|
|
||||||
__n = numeric_limits<streamsize>::max() / sizeof(_CharT) - 1;
|
|
||||||
streamsize __c = 0;
|
|
||||||
const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc());
|
const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc());
|
||||||
ios_base::iostate __err = ios_base::goodbit;
|
ios_base::iostate __err = ios_base::goodbit;
|
||||||
while (__c < __n-1)
|
while (__s != __p + (__n-1))
|
||||||
{
|
{
|
||||||
typename _Traits::int_type __i = __is.rdbuf()->sgetc();
|
typename _Traits::int_type __i = __is.rdbuf()->sgetc();
|
||||||
if (_Traits::eq_int_type(__i, _Traits::eof()))
|
if (_Traits::eq_int_type(__i, _Traits::eof()))
|
||||||
@@ -545,12 +543,11 @@ operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
|||||||
if (__ct.is(__ct.space, __ch))
|
if (__ct.is(__ct.space, __ch))
|
||||||
break;
|
break;
|
||||||
*__s++ = __ch;
|
*__s++ = __ch;
|
||||||
++__c;
|
|
||||||
__is.rdbuf()->sbumpc();
|
__is.rdbuf()->sbumpc();
|
||||||
}
|
}
|
||||||
*__s = _CharT();
|
*__s = _CharT();
|
||||||
__is.width(0);
|
__is.width(0);
|
||||||
if (__c == 0)
|
if (__s == __p)
|
||||||
__err |= ios_base::failbit;
|
__err |= ios_base::failbit;
|
||||||
__is.setstate(__err);
|
__is.setstate(__err);
|
||||||
}
|
}
|
||||||
@@ -564,6 +561,48 @@ operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
|||||||
return __is;
|
return __is;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _LIBCPP_STD_VER > 17
|
||||||
|
|
||||||
|
template<class _CharT, class _Traits, size_t _Np>
|
||||||
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
|
basic_istream<_CharT, _Traits>&
|
||||||
|
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT (&__buf)[_Np])
|
||||||
|
{
|
||||||
|
auto __n = _Np;
|
||||||
|
if (__is.width() > 0)
|
||||||
|
__n = _VSTD::min(size_t(__is.width()), _Np);
|
||||||
|
return _VSTD::__input_c_string(__is, __buf, __n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class _Traits, size_t _Np>
|
||||||
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
|
basic_istream<char, _Traits>&
|
||||||
|
operator>>(basic_istream<char, _Traits>& __is, unsigned char (&__buf)[_Np])
|
||||||
|
{
|
||||||
|
return __is >> (char(&)[_Np])__buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class _Traits, size_t _Np>
|
||||||
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
|
basic_istream<char, _Traits>&
|
||||||
|
operator>>(basic_istream<char, _Traits>& __is, signed char (&__buf)[_Np])
|
||||||
|
{
|
||||||
|
return __is >> (char(&)[_Np])__buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template<class _CharT, class _Traits>
|
||||||
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
|
basic_istream<_CharT, _Traits>&
|
||||||
|
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
|
||||||
|
{
|
||||||
|
streamsize __n = __is.width();
|
||||||
|
if (__n <= 0)
|
||||||
|
__n = numeric_limits<streamsize>::max() / sizeof(_CharT) - 1;
|
||||||
|
return _VSTD::__input_c_string(__is, __s, size_t(__n));
|
||||||
|
}
|
||||||
|
|
||||||
template<class _Traits>
|
template<class _Traits>
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
basic_istream<char, _Traits>&
|
basic_istream<char, _Traits>&
|
||||||
@@ -580,6 +619,8 @@ operator>>(basic_istream<char, _Traits>& __is, signed char* __s)
|
|||||||
return __is >> (char*)__s;
|
return __is >> (char*)__s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // _LIBCPP_STD_VER > 17
|
||||||
|
|
||||||
template<class _CharT, class _Traits>
|
template<class _CharT, class _Traits>
|
||||||
basic_istream<_CharT, _Traits>&
|
basic_istream<_CharT, _Traits>&
|
||||||
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT& __c)
|
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT& __c)
|
||||||
|
|||||||
@@ -61,6 +61,17 @@ int main()
|
|||||||
assert(std::string((char*)s) == "abc");
|
assert(std::string((char*)s) == "abc");
|
||||||
assert(is.width() == 0);
|
assert(is.width() == 0);
|
||||||
}
|
}
|
||||||
|
#if TEST_STD_VER > 17
|
||||||
|
{
|
||||||
|
testbuf<char> sb(" abcdefghijk ");
|
||||||
|
std::istream is(&sb);
|
||||||
|
signed char s[4];
|
||||||
|
is >> s;
|
||||||
|
assert(!is.eof());
|
||||||
|
assert(!is.fail());
|
||||||
|
assert(std::string((char*)s) == "abc");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
testbuf<char> sb(" abcdefghijk");
|
testbuf<char> sb(" abcdefghijk");
|
||||||
std::istream is(&sb);
|
std::istream is(&sb);
|
||||||
@@ -82,4 +93,15 @@ int main()
|
|||||||
assert(std::string((char*)s) == "");
|
assert(std::string((char*)s) == "");
|
||||||
assert(is.width() == 0);
|
assert(is.width() == 0);
|
||||||
}
|
}
|
||||||
|
#if TEST_STD_VER > 17
|
||||||
|
{
|
||||||
|
testbuf<char> sb(" abcdefghijk");
|
||||||
|
std::istream is(&sb);
|
||||||
|
signed char s[1];
|
||||||
|
is >> s;
|
||||||
|
assert(!is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::string((char*)s) == "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,17 @@ int main()
|
|||||||
assert(std::string((char*)s) == "abc");
|
assert(std::string((char*)s) == "abc");
|
||||||
assert(is.width() == 0);
|
assert(is.width() == 0);
|
||||||
}
|
}
|
||||||
|
#if TEST_STD_VER > 17
|
||||||
|
{
|
||||||
|
testbuf<char> sb(" abcdefghijk ");
|
||||||
|
std::istream is(&sb);
|
||||||
|
unsigned char s[4];
|
||||||
|
is >> s;
|
||||||
|
assert(!is.eof());
|
||||||
|
assert(!is.fail());
|
||||||
|
assert(std::string((char*)s) == "abc");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
testbuf<char> sb(" abcdefghijk");
|
testbuf<char> sb(" abcdefghijk");
|
||||||
std::istream is(&sb);
|
std::istream is(&sb);
|
||||||
@@ -82,4 +93,15 @@ int main()
|
|||||||
assert(std::string((char*)s) == "");
|
assert(std::string((char*)s) == "");
|
||||||
assert(is.width() == 0);
|
assert(is.width() == 0);
|
||||||
}
|
}
|
||||||
|
#if TEST_STD_VER > 17
|
||||||
|
{
|
||||||
|
testbuf<char> sb(" abcdefghijk");
|
||||||
|
std::istream is(&sb);
|
||||||
|
unsigned char s[1];
|
||||||
|
is >> s;
|
||||||
|
assert(!is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::string((char*)s) == "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,17 @@ int main()
|
|||||||
assert(!is.fail());
|
assert(!is.fail());
|
||||||
assert(std::string(s) == "abcdefghijk");
|
assert(std::string(s) == "abcdefghijk");
|
||||||
}
|
}
|
||||||
|
#if TEST_STD_VER > 17
|
||||||
|
{
|
||||||
|
testbuf<char> sb(" abcdefghijk ");
|
||||||
|
std::istream is(&sb);
|
||||||
|
char s[4];
|
||||||
|
is >> s;
|
||||||
|
assert(!is.eof());
|
||||||
|
assert(!is.fail());
|
||||||
|
assert(std::string(s) == "abc");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
testbuf<wchar_t> sb(L" abcdefghijk ");
|
testbuf<wchar_t> sb(L" abcdefghijk ");
|
||||||
std::wistream is(&sb);
|
std::wistream is(&sb);
|
||||||
@@ -71,6 +82,17 @@ int main()
|
|||||||
assert(std::wstring(s) == L"abcdefghijk");
|
assert(std::wstring(s) == L"abcdefghijk");
|
||||||
assert(is.width() == 0);
|
assert(is.width() == 0);
|
||||||
}
|
}
|
||||||
|
#if TEST_STD_VER > 17
|
||||||
|
{
|
||||||
|
testbuf<wchar_t> sb(L" abcdefghijk");
|
||||||
|
std::wistream is(&sb);
|
||||||
|
wchar_t s[4];
|
||||||
|
is >> s;
|
||||||
|
assert(!is.eof());
|
||||||
|
assert(!is.fail());
|
||||||
|
assert(std::wstring(s) == L"abc");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
testbuf<char> sb(" abcdefghijk");
|
testbuf<char> sb(" abcdefghijk");
|
||||||
std::istream is(&sb);
|
std::istream is(&sb);
|
||||||
@@ -82,4 +104,15 @@ int main()
|
|||||||
assert(std::string(s) == "");
|
assert(std::string(s) == "");
|
||||||
assert(is.width() == 0);
|
assert(is.width() == 0);
|
||||||
}
|
}
|
||||||
|
#if TEST_STD_VER > 17
|
||||||
|
{
|
||||||
|
testbuf<char> sb(" abcdefghijk");
|
||||||
|
std::istream is(&sb);
|
||||||
|
char s[1];
|
||||||
|
is >> s;
|
||||||
|
assert(!is.eof());
|
||||||
|
assert( is.fail());
|
||||||
|
assert(std::string(s) == "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@
|
|||||||
<tr><td><a href="https://wg21.link/P0356R5">P0356R5</a></td><td>LWG</td><td>Simplified partial function application</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
<tr><td><a href="https://wg21.link/P0356R5">P0356R5</a></td><td>LWG</td><td>Simplified partial function application</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
||||||
<tr><td><a href="https://wg21.link/P0357R3">P0357R3</a></td><td>LWG</td><td>reference_wrapper for incomplete types</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
<tr><td><a href="https://wg21.link/P0357R3">P0357R3</a></td><td>LWG</td><td>reference_wrapper for incomplete types</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
||||||
<tr><td><a href="https://wg21.link/P0482R6">P0482R6</a></td><td>CWG</td><td>char8_t: A type for UTF-8 characters and strings</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
<tr><td><a href="https://wg21.link/P0482R6">P0482R6</a></td><td>CWG</td><td>char8_t: A type for UTF-8 characters and strings</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
||||||
<tr><td><a href="https://wg21.link/P0487R1">P0487R1</a></td><td>LWG</td><td>Fixing operator>>(basic_istream&, CharT*) (LWG 2499)</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
<tr><td><a href="https://wg21.link/P0487R1">P0487R1</a></td><td>LWG</td><td>Fixing operator>>(basic_istream&, CharT*) (LWG 2499)</td><td>San Diego</td><td>Complete</td><td>8.0</td></tr>
|
||||||
<tr><td><a href="https://wg21.link/P0591R4">P0591R4</a></td><td>LWG</td><td>Utility functions to implement uses-allocator construction</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
<tr><td><a href="https://wg21.link/P0591R4">P0591R4</a></td><td>LWG</td><td>Utility functions to implement uses-allocator construction</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
||||||
<tr><td><a href="https://wg21.link/P0595R2">P0595R2</a></td><td>CWG</td><td>P0595R2 std::is_constant_evaluated()</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
<tr><td><a href="https://wg21.link/P0595R2">P0595R2</a></td><td>CWG</td><td>P0595R2 std::is_constant_evaluated()</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
||||||
<tr><td><a href="https://wg21.link/P0602R4">P0602R4</a></td><td>LWG</td><td>variant and optional should propagate copy/move triviality</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
<tr><td><a href="https://wg21.link/P0602R4">P0602R4</a></td><td>LWG</td><td>variant and optional should propagate copy/move triviality</td><td>San Diego</td><td><i> </i></td><td></td></tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user