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

Volodymyr Sapsai via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 22 10:52:36 PST 2017


Author: vsapsai
Date: Wed Nov 22 10:52:36 2017
New Revision: 318862

URL: http://llvm.org/viewvc/llvm-project?rev=318862&view=rev
Log:
[libcxx] Make std::basic_istream::getline 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]p21:
  In any case, if n is greater than zero, it then stores a null character
  (using charT()) into the next successive location of the array.

Patch by Reimar Döffinger.


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

Modified: libcxx/trunk/include/istream
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/istream?rev=318862&r1=318861&r2=318862&view=diff
==============================================================================
--- libcxx/trunk/include/istream (original)
+++ libcxx/trunk/include/istream Wed Nov 22 10:52:36 2017
@@ -1069,16 +1069,18 @@ basic_istream<_CharT, _Traits>::getline(
                 this->rdbuf()->sbumpc();
                 ++__gc_;
             }
-            if (__n > 0)
-                *__s = char_type();
             if (__gc_ == 0)
                __err |= ios_base::failbit;
             this->setstate(__err);
         }
+        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/getline_pointer_size.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/getline_pointer_size.pass.cpp?rev=318862&r1=318861&r2=318862&view=diff
==============================================================================
--- libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/getline_pointer_size.pass.cpp (original)
+++ libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/getline_pointer_size.pass.cpp Wed Nov 22 10:52:36 2017
@@ -14,6 +14,8 @@
 #include <istream>
 #include <cassert>
 
+#include "test_macros.h"
+
 template <class CharT>
 struct testbuf
     : public std::basic_streambuf<CharT>
@@ -59,7 +61,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.getline(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.getline(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);
@@ -79,5 +107,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.getline(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.getline(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/getline_pointer_size_chart.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/getline_pointer_size_chart.pass.cpp?rev=318862&r1=318861&r2=318862&view=diff
==============================================================================
--- libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/getline_pointer_size_chart.pass.cpp (original)
+++ libcxx/trunk/test/std/input.output/iostream.format/input.streams/istream.unformatted/getline_pointer_size_chart.pass.cpp Wed Nov 22 10:52:36 2017
@@ -14,6 +14,8 @@
 #include <istream>
 #include <cassert>
 
+#include "test_macros.h"
+
 template <class CharT>
 struct testbuf
     : public std::basic_streambuf<CharT>
@@ -59,7 +61,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.getline(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.getline(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);
@@ -79,5 +107,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.getline(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.getline(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