This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[v3] Fix libstdc++/11544 and 11603


Hi,

pretty simple, tested x86-linux, committed.

Paolo.

/////////////
2003-11-27  Paolo Carlini  <pcarlini@suse.de>

	PR libstdc++/11544
	PR libstdc++/11603
	* include/bits/fstream.tcc (underflow): Throw ios_base:failure
	upon incomplete or invalid byte sequences in the file.
	* testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-1.cc: New.
	* testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-2.cc: New.
	* testsuite/27_io/basic_filebuf/underflow/wchar_t/11603.cc: New.

	
diff -prN libstdc++-v3-orig/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
*** libstdc++-v3-orig/include/bits/fstream.tcc	Thu Nov 27 14:15:25 2003
--- libstdc++-v3/include/bits/fstream.tcc	Thu Nov 27 18:33:52 2003
*************** namespace std
*** 201,206 ****
--- 201,207 ----
  	  bool __got_eof = false;
  	  // Number of internal characters produced.
  	  streamsize __ilen = 0;
+ 	  codecvt_base::result __r = codecvt_base::ok;	  
  	  if (__check_facet(_M_codecvt).always_noconv())
  	    {
  	      __ilen = _M_file.xsgetn(reinterpret_cast<char*>(this->eback()), 
*************** namespace std
*** 261,269 ****
  			__got_eof = true;
  		      _M_ext_end += __elen;
  		    }
! 		  
  		  char_type* __iend;
- 		  codecvt_base::result __r;
  		  __r = _M_codecvt->in(_M_state_cur, _M_ext_next,
  				       _M_ext_end, _M_ext_next, this->eback(), 
  				       this->eback() + __buflen, __iend);
--- 262,269 ----
  			__got_eof = true;
  		      _M_ext_end += __elen;
  		    }
! 
  		  char_type* __iend;
  		  __r = _M_codecvt->in(_M_state_cur, _M_ext_next,
  				       _M_ext_end, _M_ext_next, this->eback(), 
  				       this->eback() + __buflen, __iend);
*************** namespace std
*** 277,283 ****
  		    }
  		  else
  		    __ilen = __iend - this->eback();
! 		  
  		  // _M_codecvt->in may return error while __ilen > 0: this is
  		  // ok, and actually occurs in case of mixed encodings (e.g.,
  		  // XML files).
--- 277,283 ----
  		    }
  		  else
  		    __ilen = __iend - this->eback();
! 
  		  // _M_codecvt->in may return error while __ilen > 0: this is
  		  // ok, and actually occurs in case of mixed encodings (e.g.,
  		  // XML files).
*************** namespace std
*** 302,308 ****
--- 302,314 ----
  	      // intervening seek.
  	      _M_set_buffer(-1);
  	      _M_reading = false;
+ 	      // However, reaching it while looping on partial means that
+ 	      // the file has got an incomplete character.
+ 	      if (__r == codecvt_base::partial)
+ 		__throw_ios_failure("incomplete character in file");
  	    }
+ 	  else if (__r == codecvt_base::error)
+ 	    __throw_ios_failure("invalid byte sequence in file");
  	}
        return __ret;
      }
diff -prN libstdc++-v3-orig/testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-1.cc libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-1.cc
*** libstdc++-v3-orig/testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-1.cc	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-1.cc	Thu Nov 27 18:15:28 2003
***************
*** 0 ****
--- 1,185 ----
+ // Copyright (C) 2003 Free Software Foundation, Inc.
+ //
+ // This file is part of the GNU ISO C++ Library.  This library is free
+ // software; you can redistribute it and/or modify it under the
+ // terms of the GNU General Public License as published by the
+ // Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ 
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ // GNU General Public License for more details.
+ 
+ // You should have received a copy of the GNU General Public License along
+ // with this library; see the file COPYING.  If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+ 
+ // 27.8.1.4 Overridden virtual functions
+ 
+ #include <fstream>
+ #include <locale>
+ #include <cstdio>
+ #include <testsuite_hooks.h>
+ 
+ template <typename InternT, typename StateT = mbstate_t>
+ class checksumcvt : public std::codecvt<InternT, char, StateT>
+ {
+   typedef std::codecvt<InternT, char, StateT> Base;
+   static const size_t width = sizeof(InternT) + 1;
+ 
+ public:
+   typedef InternT intern_type;
+   typedef char extern_type;
+ 
+   explicit checksumcvt(size_t refs = 0)
+   : Base(refs)
+   { }
+ 
+ protected:
+   virtual typename std::codecvt<InternT, char, StateT>::result
+   do_out(StateT&, const intern_type* from,
+ 	 const intern_type* from_end, const intern_type*& from_next,
+ 	 extern_type* to, extern_type* to_end,
+ 	 extern_type*& to_next) const
+   {
+     size_t len = std::min(static_cast<size_t>(from_end - from),
+ 			  static_cast<size_t>(to_end - to) / width);
+ 
+     while (len--)
+       {
+ 	const char* p = reinterpret_cast<const char*>(from);
+ 	unsigned char checksum = 0;
+ 				
+ 	for (size_t i = 0; i < sizeof(intern_type); ++i)
+ 	  {
+ 	    *to++ = p[i];
+ 	    checksum ^= static_cast<unsigned char>(p[i]);
+ 	  }
+ 
+ 	*to++ = checksum;
+ 	++from;
+       }
+ 
+     from_next = from;
+     to_next = to;
+     return from_next == from_end ? std::codecvt<InternT, char, StateT>::ok
+            : std::codecvt<InternT, char, StateT>::partial;
+   }
+ 
+   virtual typename std::codecvt<InternT, char, StateT>::result
+   do_unshift(StateT&, extern_type* to,
+ 	     extern_type*, extern_type*& to_next) const
+   {
+     to_next = to;
+     return std::codecvt<InternT, char, StateT>::ok;
+   }
+ 
+   virtual typename std::codecvt<InternT, char, StateT>::result
+   do_in(StateT&, const extern_type* from,
+ 	const extern_type* from_end, const extern_type*& from_next,
+ 	intern_type* to, intern_type* to_end,
+ 	intern_type*& to_next) const
+   {
+     size_t len = std::min(static_cast<size_t>(to_end - to),
+ 			  static_cast<size_t>(from_end - from) / width);
+ 			
+     while (len)
+       {
+ 	const char* f = from;
+ 	intern_type tmp;
+ 	char* p = reinterpret_cast<char*>(&tmp);
+ 	unsigned char checksum = 0;
+ 
+ 	for (size_t i = 0; i < sizeof(intern_type); ++i)
+ 	  {
+ 	    p[i] = *f;
+ 	    checksum ^= static_cast<unsigned char>(*f++);
+ 	  }
+ 
+ 	if (*f++ != checksum)
+ 	  break;
+ 
+ 	from = f;
+ 	*to++ = tmp;
+ 	len--;
+       }
+ 
+     from_next = from;
+     to_next = to;
+     return len ? std::codecvt<InternT, char, StateT>::error :
+       (from_next == from_end ? std::codecvt<InternT, char, StateT>::ok
+        : std::codecvt<InternT, char, StateT>::partial);
+   }
+ 
+   virtual int
+   do_encoding() const throw()
+   { return width; }
+ 
+   virtual int
+   do_length(StateT&, const extern_type* from,
+ 	    const extern_type* end, size_t max) const
+   {
+     size_t len = std::min(max, static_cast<size_t>(end - from) / width);
+ 
+     int ret = 0;
+     while (len--)
+       {
+ 	unsigned char checksum = 0;
+ 
+ 	for (size_t i = 0; i < sizeof(intern_type); ++i)
+ 	  {
+ 	    checksum ^= static_cast<unsigned char>(*from++);
+ 	  }
+ 
+ 	if (*from++ != checksum)
+ 	  break;
+ 
+ 	ret++;
+       }
+ 
+     return ret;
+   }
+ 
+   virtual int
+   do_max_length() const throw()
+   { return width; }
+ 
+   virtual bool
+   do_always_noconv() const throw()
+   { return false; }
+ };
+ 
+ // libstdc++/11544 (incomplete character in file)
+ void test01()
+ {
+   using namespace std;
+   bool test __attribute__((unused)) = true;
+ 
+   locale loc(locale::classic(), new checksumcvt<wchar_t>);
+ 
+   const char* name = "tmp_11544-1";
+   
+   FILE* f = fopen(name, "w");
+   putc('a', f);
+   fclose(f);
+   
+   wifstream in;
+   in.imbue(loc);
+   in.open(name);
+   
+   VERIFY( in.good() );
+   in.get();
+   VERIFY( !in.good() );
+   VERIFY( in.bad() );
+   VERIFY( !in.eof() );
+   
+   in.close();
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }
diff -prN libstdc++-v3-orig/testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-2.cc libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-2.cc
*** libstdc++-v3-orig/testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-2.cc	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/11544-2.cc	Thu Nov 27 18:15:59 2003
***************
*** 0 ****
--- 1,185 ----
+ // Copyright (C) 2003 Free Software Foundation, Inc.
+ //
+ // This file is part of the GNU ISO C++ Library.  This library is free
+ // software; you can redistribute it and/or modify it under the
+ // terms of the GNU General Public License as published by the
+ // Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ 
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ // GNU General Public License for more details.
+ 
+ // You should have received a copy of the GNU General Public License along
+ // with this library; see the file COPYING.  If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+ 
+ // 27.8.1.4 Overridden virtual functions
+ 
+ #include <fstream>
+ #include <locale>
+ #include <cstdio>
+ #include <testsuite_hooks.h>
+ 
+ template <typename InternT, typename StateT = mbstate_t>
+ class checksumcvt : public std::codecvt<InternT, char, StateT>
+ {
+   typedef std::codecvt<InternT, char, StateT> Base;
+   static const size_t width = sizeof(InternT) + 1;
+ 
+ public:
+   typedef InternT intern_type;
+   typedef char extern_type;
+ 
+   explicit checksumcvt(size_t refs = 0)
+   : Base(refs)
+   { }
+ 
+ protected:
+   virtual typename std::codecvt<InternT, char, StateT>::result
+   do_out(StateT&, const intern_type* from,
+ 	 const intern_type* from_end, const intern_type*& from_next,
+ 	 extern_type* to, extern_type* to_end,
+ 	 extern_type*& to_next) const
+   {
+     size_t len = std::min(static_cast<size_t>(from_end - from),
+ 			  static_cast<size_t>(to_end - to) / width);
+ 
+     while (len--)
+       {
+ 	const char* p = reinterpret_cast<const char*>(from);
+ 	unsigned char checksum = 0;
+ 				
+ 	for (size_t i = 0; i < sizeof(intern_type); ++i)
+ 	  {
+ 	    *to++ = p[i];
+ 	    checksum ^= static_cast<unsigned char>(p[i]);
+ 	  }
+ 
+ 	*to++ = checksum;
+ 	++from;
+       }
+ 
+     from_next = from;
+     to_next = to;
+     return from_next == from_end ? std::codecvt<InternT, char, StateT>::ok
+            : std::codecvt<InternT, char, StateT>::partial;
+   }
+ 
+   virtual typename std::codecvt<InternT, char, StateT>::result
+   do_unshift(StateT&, extern_type* to,
+ 	     extern_type*, extern_type*& to_next) const
+   {
+     to_next = to;
+     return std::codecvt<InternT, char, StateT>::ok;
+   }
+ 
+   virtual typename std::codecvt<InternT, char, StateT>::result
+   do_in(StateT&, const extern_type* from,
+ 	const extern_type* from_end, const extern_type*& from_next,
+ 	intern_type* to, intern_type* to_end,
+ 	intern_type*& to_next) const
+   {
+     size_t len = std::min(static_cast<size_t>(to_end - to),
+ 			  static_cast<size_t>(from_end - from) / width);
+ 			
+     while (len)
+       {
+ 	const char* f = from;
+ 	intern_type tmp;
+ 	char* p = reinterpret_cast<char*>(&tmp);
+ 	unsigned char checksum = 0;
+ 
+ 	for (size_t i = 0; i < sizeof(intern_type); ++i)
+ 	  {
+ 	    p[i] = *f;
+ 	    checksum ^= static_cast<unsigned char>(*f++);
+ 	  }
+ 
+ 	if (*f++ != checksum)
+ 	  break;
+ 
+ 	from = f;
+ 	*to++ = tmp;
+ 	len--;
+       }
+ 
+     from_next = from;
+     to_next = to;
+     return len ? std::codecvt<InternT, char, StateT>::error :
+       (from_next == from_end ? std::codecvt<InternT, char, StateT>::ok
+        : std::codecvt<InternT, char, StateT>::partial);
+   }
+ 
+   virtual int
+   do_encoding() const throw()
+   { return width; }
+ 
+   virtual int
+   do_length(StateT&, const extern_type* from,
+ 	    const extern_type* end, size_t max) const
+   {
+     size_t len = std::min(max, static_cast<size_t>(end - from) / width);
+ 
+     int ret = 0;
+     while (len--)
+       {
+ 	unsigned char checksum = 0;
+ 
+ 	for (size_t i = 0; i < sizeof(intern_type); ++i)
+ 	  {
+ 	    checksum ^= static_cast<unsigned char>(*from++);
+ 	  }
+ 
+ 	if (*from++ != checksum)
+ 	  break;
+ 
+ 	ret++;
+       }
+ 
+     return ret;
+   }
+ 
+   virtual int
+   do_max_length() const throw()
+   { return width; }
+ 
+   virtual bool
+   do_always_noconv() const throw()
+   { return false; }
+ };
+ 
+ // libstdc++/11544 (invalid byte sequence in file)
+ void test02()
+ {
+   using namespace std;
+   bool test __attribute__((unused)) = true;
+ 
+   locale loc(locale::classic(), new checksumcvt<wchar_t>);
+   
+   const char* name = "tmp_11544-2";
+   
+   FILE* f = fopen(name, "w");
+   fwrite("aaaab", 1, 5, f);
+   fclose(f);
+   
+   wifstream in;
+   in.imbue(loc);
+   in.open(name);
+   
+   VERIFY( in.good() );
+   in.get();
+   VERIFY( !in.good() );
+   VERIFY( in.bad() );
+   VERIFY( !in.eof() );
+   
+   in.close();
+ }
+ 
+ int main()
+ {
+   test02();
+   return 0;
+ }
diff -prN libstdc++-v3-orig/testsuite/27_io/basic_filebuf/underflow/wchar_t/11603.cc libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/11603.cc
*** libstdc++-v3-orig/testsuite/27_io/basic_filebuf/underflow/wchar_t/11603.cc	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/wchar_t/11603.cc	Thu Nov 27 18:17:05 2003
***************
*** 0 ****
--- 1,200 ----
+ // Copyright (C) 2003 Free Software Foundation, Inc.
+ //
+ // This file is part of the GNU ISO C++ Library.  This library is free
+ // software; you can redistribute it and/or modify it under the
+ // terms of the GNU General Public License as published by the
+ // Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ 
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ // GNU General Public License for more details.
+ 
+ // You should have received a copy of the GNU General Public License along
+ // with this library; see the file COPYING.  If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+ 
+ // 27.8.1.4 Overridden virtual functions
+ 
+ #include <fstream>
+ #include <locale>
+ #include <testsuite_hooks.h>
+ 
+ template <typename InternT, typename StateT = std::mbstate_t>
+ class checksumcvt : public std::codecvt<InternT, char, StateT>
+ {
+   typedef std::codecvt<InternT, char, StateT> Base;
+   static const std::size_t width = sizeof(InternT) + 1;
+ 
+ public:
+   typedef InternT intern_type;
+   typedef char extern_type;
+ 
+   explicit checksumcvt(std::size_t refs = 0)
+     : Base(refs)
+   { }
+ 
+ protected:
+   virtual std::codecvt_base::result
+   do_out(StateT&, const intern_type* from,
+ 	 const intern_type* from_end, const intern_type*& from_next,
+ 	 extern_type* to, extern_type* to_end,
+ 	 extern_type*& to_next) const
+   {
+     size_t len = std::min(static_cast<size_t>(from_end - from),
+ 			  static_cast<size_t>(to_end - to) / width);
+ 
+     while (len--)
+       {
+ 	const char* p =
+ 	  reinterpret_cast<const char*>(from);
+ 	unsigned char checksum = 0;
+ 				
+ 	for (std::size_t i = 0; i < sizeof(intern_type); ++i)
+ 	  {
+ 	    *to++ = p[i];
+ 	    checksum ^= static_cast<unsigned char>(p[i]);
+ 	  }
+ 
+ 	*to++ = checksum;
+ 	++from;
+       }
+ 
+     from_next = from;
+     to_next = to;
+     return from_next == from_end ? std::codecvt_base::ok 
+                                  : std::codecvt_base::partial;
+   }
+ 
+   virtual std::codecvt_base::result
+   do_unshift(StateT&, extern_type* to,
+ 	     extern_type*, extern_type*& to_next) const
+   {
+     to_next = to;
+     return std::codecvt_base::ok;
+   }
+ 
+   virtual std::codecvt_base::result
+   do_in(StateT&, const extern_type* from,
+ 	const extern_type* from_end, const extern_type*& from_next,
+ 	intern_type* to, intern_type* to_end,
+ 	intern_type*& to_next) const
+   {
+     size_t len = std::min(static_cast<size_t>(to_end - to),
+ 			  static_cast<size_t>(from_end - from) / width);
+ 			
+     while (len)
+       {
+ 	const char* f = from;
+ 	intern_type tmp;
+ 	char* p = reinterpret_cast<char*>(&tmp);
+ 	unsigned char checksum = 0;
+ 
+ 	for (std::size_t i = 0; i < sizeof(intern_type); ++i)
+ 	  {
+ 	    p[i] = *f;
+ 	    checksum ^= static_cast<unsigned char>(*f++);
+ 	  }
+ 
+ 	if (*f++ != checksum)
+ 	  break;
+ 
+ 	from = f;
+ 	*to++ = tmp;
+ 	len--;
+       }
+ 
+     from_next = from;
+     to_next = to;
+     return len ? std::codecvt_base::error :
+       (from_next == from_end ? std::codecvt_base::ok
+                              : std::codecvt_base::partial);
+   }
+ 
+   virtual int
+   do_encoding() const throw()
+   { return width; }
+ 
+   virtual int
+   do_length(const StateT&, const extern_type* from,
+ 	    const extern_type* end, size_t max) const
+   {
+     size_t len = std::min(max,
+ 			  static_cast<size_t>(end - from) / width);
+ 
+     int ret = 0;
+     while (len--)
+       {
+ 	unsigned char checksum = 0;
+ 
+ 	for (std::size_t i = 0; i < sizeof(intern_type); ++i)
+ 	  {
+ 	    checksum ^= static_cast<unsigned char>(*from++);
+ 	  }
+ 
+ 	if (*from++ != checksum)
+ 	  break;
+ 
+ 	ret++;
+       }
+ 
+     return ret;
+   }
+ 
+   virtual int
+   do_max_length() const throw()
+   { return width; }
+ 
+   virtual bool
+   do_always_noconv() const throw()
+   { return false; }
+ };
+ 
+ class Buf : public std::wfilebuf
+ {
+ public:
+   std::streamsize pub_showmanyc()
+   { return showmanyc(); }
+   std::wfilebuf::int_type pub_underflow()
+   { return underflow(); }
+ };
+ 
+ // libstdc++/11603
+ void test01()
+ {
+   using namespace std;
+   bool test __attribute__((unused)) = true;
+ 
+   filebuf fbout;
+   fbout.open("tmp_11603", ios_base::out);
+   fbout.sputn("aaaab", 5);
+   fbout.close();
+ 
+   locale loc(locale::classic(), new checksumcvt<wchar_t>);
+   
+   Buf fb;
+   fb.pubimbue(loc);
+   fb.open("tmp_11603", ios_base::in);
+   assert(fb.pub_showmanyc() == 1);
+   
+   try
+     {
+       wfilebuf::int_type ret = fb.pub_underflow();
+       VERIFY( ret != wfilebuf::traits_type::eof() );
+       fb.sbumpc();
+       ret = fb.pub_underflow();
+       VERIFY( ret == wfilebuf::traits_type::eof() );
+     }
+   catch (...)
+     { }
+ 
+   fb.close();
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]