[libcxx] r347377 - [libc++] Implement P0487R1 - Fixing operator>>(basic_istream&, CharT*)

Zhihao Yuan zy at miator.net
Tue Nov 20 19:30:10 PST 2018


Author: lichray
Date: Tue Nov 20 19:30:10 2018
New Revision: 347377

URL: http://llvm.org/viewvc/llvm-project?rev=347377&view=rev
Log:
[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

Modified:
    libcxx/trunk/include/istream
    libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/signed_char_pointer.pass.cpp
    libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/unsigned_char_pointer.pass.cpp
    libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/wchar_t_pointer.pass.cpp
    libcxx/trunk/www/cxx2a_status.html

Modified: libcxx/trunk/include/istream
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/istream?rev=347377&r1=347376&r2=347377&view=diff
==============================================================================
--- libcxx/trunk/include/istream (original)
+++ libcxx/trunk/include/istream Tue Nov 20 19:30:10 2018
@@ -517,8 +517,9 @@ basic_istream<_CharT, _Traits>::operator
 }
 
 template<class _CharT, class _Traits>
+_LIBCPP_INLINE_VISIBILITY
 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
     try
@@ -527,13 +528,10 @@ operator>>(basic_istream<_CharT, _Traits
         typename basic_istream<_CharT, _Traits>::sentry __sen(__is);
         if (__sen)
         {
-            streamsize __n = __is.width();
-            if (__n <= 0)
-                __n = numeric_limits<streamsize>::max() / sizeof(_CharT) - 1;
-            streamsize __c = 0;
+            auto __s = __p;
             const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__is.getloc());
             ios_base::iostate __err = ios_base::goodbit;
-            while (__c < __n-1)
+            while (__s != __p + (__n-1))
             {
                 typename _Traits::int_type __i = __is.rdbuf()->sgetc();
                 if (_Traits::eq_int_type(__i, _Traits::eof()))
@@ -545,12 +543,11 @@ operator>>(basic_istream<_CharT, _Traits
                 if (__ct.is(__ct.space, __ch))
                     break;
                 *__s++ = __ch;
-                ++__c;
                  __is.rdbuf()->sbumpc();
             }
             *__s = _CharT();
             __is.width(0);
-            if (__c == 0)
+            if (__s == __p)
                __err |= ios_base::failbit;
             __is.setstate(__err);
         }
@@ -564,6 +561,48 @@ operator>>(basic_istream<_CharT, _Traits
     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>
 inline _LIBCPP_INLINE_VISIBILITY
 basic_istream<char, _Traits>&
@@ -580,6 +619,8 @@ operator>>(basic_istream<char, _Traits>&
     return __is >> (char*)__s;
 }
 
+#endif  // _LIBCPP_STD_VER > 17
+
 template<class _CharT, class _Traits>
 basic_istream<_CharT, _Traits>&
 operator>>(basic_istream<_CharT, _Traits>& __is, _CharT& __c)

Modified: libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/signed_char_pointer.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/signed_char_pointer.pass.cpp?rev=347377&r1=347376&r2=347377&view=diff
==============================================================================
--- libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/signed_char_pointer.pass.cpp (original)
+++ libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/signed_char_pointer.pass.cpp Tue Nov 20 19:30:10 2018
@@ -61,6 +61,17 @@ int main()
         assert(std::string((char*)s) == "abc");
         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");
         std::istream is(&sb);
@@ -82,4 +93,15 @@ int main()
         assert(std::string((char*)s) == "");
         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
 }

Modified: libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/unsigned_char_pointer.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/unsigned_char_pointer.pass.cpp?rev=347377&r1=347376&r2=347377&view=diff
==============================================================================
--- libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/unsigned_char_pointer.pass.cpp (original)
+++ libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/unsigned_char_pointer.pass.cpp Tue Nov 20 19:30:10 2018
@@ -61,6 +61,17 @@ int main()
         assert(std::string((char*)s) == "abc");
         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");
         std::istream is(&sb);
@@ -82,4 +93,15 @@ int main()
         assert(std::string((char*)s) == "");
         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
 }

Modified: libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/wchar_t_pointer.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/wchar_t_pointer.pass.cpp?rev=347377&r1=347376&r2=347377&view=diff
==============================================================================
--- libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/wchar_t_pointer.pass.cpp (original)
+++ libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.formatted/istream_extractors/wchar_t_pointer.pass.cpp Tue Nov 20 19:30:10 2018
@@ -50,6 +50,17 @@ int main()
         assert(!is.fail());
         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    ");
         std::wistream is(&sb);
@@ -71,6 +82,17 @@ int main()
         assert(std::wstring(s) == L"abcdefghijk");
         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");
         std::istream is(&sb);
@@ -82,4 +104,15 @@ int main()
         assert(std::string(s) == "");
         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
 }

Modified: libcxx/trunk/www/cxx2a_status.html
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx2a_status.html?rev=347377&r1=347376&r2=347377&view=diff
==============================================================================
--- libcxx/trunk/www/cxx2a_status.html (original)
+++ libcxx/trunk/www/cxx2a_status.html Tue Nov 20 19:30:10 2018
@@ -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/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/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/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>




More information about the libcxx-commits mailing list