[libcxx] r322326 - [libcxx] Make std::basic_istream::get 0-terminate input array in case of error.

Volodymyr Sapsai via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 11 15:23:49 PST 2018


Author: vsapsai
Date: Thu Jan 11 15:23:49 2018
New Revision: 322326

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

Modified:
    libcxx/trunk/include/istream
    libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size.pass.cpp
    libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size_chart.pass.cpp

Modified: libcxx/trunk/include/istream
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/istream?rev=322326&r1=322325&r2=322326&view=diff
==============================================================================
--- libcxx/trunk/include/istream (original)
+++ libcxx/trunk/include/istream Thu Jan 11 15:23:49 2018
@@ -960,7 +960,6 @@ basic_istream<_CharT, _Traits>::get(char
                     ++__gc_;
                      this->rdbuf()->sbumpc();
                 }
-                *__s = char_type();
                 if (__gc_ == 0)
                    __err |= ios_base::failbit;
                 this->setstate(__err);
@@ -968,10 +967,14 @@ basic_istream<_CharT, _Traits>::get(char
             else
                 this->setstate(ios_base::failbit);
         }
+        if (__n > 0)
+            *__s = char_type();
 #ifndef _LIBCPP_NO_EXCEPTIONS
     }
     catch (...)
     {
+        if (__n > 0)
+            *__s = char_type();
         this->__set_badbit_and_consider_rethrow();
     }
 #endif  // _LIBCPP_NO_EXCEPTIONS

Modified: libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size.pass.cpp?rev=322326&r1=322325&r2=322326&view=diff
==============================================================================
--- libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size.pass.cpp (original)
+++ libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size.pass.cpp Thu Jan 11 15:23:49 2018
@@ -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>
 
 // basic_istream<charT,traits>& get(char_type* s, streamsize n);
@@ -14,6 +22,8 @@
 #include <istream>
 #include <cassert>
 
+#include "test_macros.h"
+
 template <class CharT>
 struct testbuf
     : public std::basic_streambuf<CharT>
@@ -67,7 +77,33 @@ int main()
         assert(!is.fail());
         assert(std::string(s) == " ");
         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 ");
         std::wistream is(&sb);
@@ -95,5 +131,31 @@ int main()
         assert(!is.fail());
         assert(std::wstring(s) == L" ");
         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
 }

Modified: libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size_chart.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size_chart.pass.cpp?rev=322326&r1=322325&r2=322326&view=diff
==============================================================================
--- libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size_chart.pass.cpp (original)
+++ libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/get_pointer_size_chart.pass.cpp Thu Jan 11 15:23:49 2018
@@ -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>
 
 // basic_istream<charT,traits>& get(char_type* s, streamsize n, char_type delim);
@@ -14,6 +22,8 @@
 #include <istream>
 #include <cassert>
 
+#include "test_macros.h"
+
 template <class CharT>
 struct testbuf
     : public std::basic_streambuf<CharT>
@@ -67,7 +77,33 @@ int main()
         assert(!is.fail());
         assert(std::string(s) == " ");
         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"  *    * ");
         std::wistream is(&sb);
@@ -95,5 +131,31 @@ int main()
         assert(!is.fail());
         assert(std::wstring(s) == L" ");
         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
 }




More information about the cfe-commits mailing list