From: Jonathan Wakely Date: Mon, 14 May 2018 18:57:45 +0000 (+0100) Subject: PR libstdc++/81256 fix exception handling in basic_filebuf::close X-Git-Tag: upstream/12.2.0~31859 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e77497ab777d3dfa19224648d658220807ab7419;p=platform%2Fupstream%2Fgcc.git PR libstdc++/81256 fix exception handling in basic_filebuf::close PR libstdc++/81256 * include/bits/fstream.tcc (basic_filebuf::close): Do not swallow exceptions from _M_terminate_output(). * include/std/fstream (basic_filebuf::~basic_filebuf): Swallow any exceptions from close(). * testsuite/27_io/basic_filebuf/close/81256.cc: New. From-SVN: r260236 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e832213..46d43d7 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,12 @@ 2018-05-14 Jonathan Wakely + PR libstdc++/81256 + * include/bits/fstream.tcc (basic_filebuf::close): Do not swallow + exceptions from _M_terminate_output(). + * include/std/fstream (basic_filebuf::~basic_filebuf): Swallow any + exceptions from close(). + * testsuite/27_io/basic_filebuf/close/81256.cc: New. + * include/bits/valarray_array.h (__valarray_get_memory): Remove. (__valarray_get_storage): Call operator new directly. Remove ignored top-level restrict qualifier and add malloc attribute instead. diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index f23ff7a..08cf189 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -239,13 +239,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (!_M_terminate_output()) __testfail = true; } - __catch(__cxxabiv1::__forced_unwind&) + __catch(...) { _M_file.close(); __throw_exception_again; } - __catch(...) - { __testfail = true; } } if (!_M_file.close()) diff --git a/libstdc++-v3/include/std/fstream b/libstdc++-v3/include/std/fstream index 3a5895d..05661d9 100644 --- a/libstdc++-v3/include/std/fstream +++ b/libstdc++-v3/include/std/fstream @@ -244,7 +244,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ virtual ~basic_filebuf() - { this->close(); } + { + __try + { this->close(); } + __catch(...) + { } + } #if __cplusplus >= 201103L basic_filebuf& operator=(const basic_filebuf&) = delete; diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/81256.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/81256.cc new file mode 100644 index 0000000..aef7364 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/81256.cc @@ -0,0 +1,109 @@ +// Copyright (C) 2018 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 3, 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 COPYING3. If not see +// . + +// { dg-do run { target c++11 } } + +#include +#include +#include + +struct E : std::runtime_error +{ + E() : runtime_error("") { } +}; + +struct Cvt : std::codecvt +{ + explicit Cvt(size_t refs) : codecvt(refs) { } + + mutable int exceptions_thrown = 0; + +private: + int + do_encoding() const noexcept override + { return -1; } + + bool + do_always_noconv() const noexcept override + { return false; } + + result + do_unshift(state_type&, char*, char*, char*&) const override + { + ++exceptions_thrown; + throw E(); + } +}; + +struct filebuf : std::basic_filebuf +{ + explicit filebuf(Cvt* c) + { + std::locale loc(std::locale::classic(), c); + imbue(loc); + } +}; + +void +test01() +{ + // This facet needs to still be valid when ~basic_filebuf runs: + Cvt conv{1}; + { + filebuf fb(&conv); + fb.open("output.txt", std::wios::out); + fb.sputn(L"x", 1); + + bool caught = false; + try + { + /* [filebuf.members] p7: If one of these calls throws an exception, + * the exception is caught and rethrown after closing the file. */ + fb.close(); + } + catch (const E&) + { + caught = true; + } + VERIFY( conv.exceptions_thrown == 1 ); + VERIFY( caught ); + } + VERIFY( conv.exceptions_thrown == 1 ); +} + +void +test02() +{ + // This facet needs to still be valid when ~basic_filebuf runs: + Cvt conv{1}; + { + filebuf fb(&conv); + fb.open("output.txt", std::wios::out); + fb.sputn(L"x", 1); + /* [filebuf.cons] p5: If an exception occurs during the destruction + * of the object, including the call to close(), the exception is + * caught but not rethrown. */ + } + VERIFY( conv.exceptions_thrown == 1 ); +} + +int +main() +{ + test01(); + test02(); +}