diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index cfbd155148..c81edf674b 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -407,14 +407,13 @@ public: else if ( fmt == FileStorage::FORMAT_JSON ) puts( "}\n" ); } - - closeFile(); if( mem_mode && out ) { *out = cv::String(outbuf.begin(), outbuf.end()); } - init(); } + closeFile(); + init(); } void analyze_file_name( const std::string& file_name, std::vector& params ) @@ -1825,10 +1824,18 @@ FileStorage::~FileStorage() bool FileStorage::open(const String& filename, int flags, const String& encoding) { - bool ok = p->open(filename.c_str(), flags, encoding.c_str()); - if(ok) - state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP; - return ok; + try + { + bool ok = p->open(filename.c_str(), flags, encoding.c_str()); + if(ok) + state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP; + return ok; + } + catch (...) + { + release(); + throw; // re-throw + } } bool FileStorage::isOpened() const { return p->is_opened; } diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index d1749e4906..965185e5f6 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -1711,4 +1711,65 @@ TEST(Core_InputOutput, FileStorage_JSON_VeryLongLines) } } +TEST(Core_InputOutput, FileStorage_empty_16823) +{ + std::string fname = tempfile("test_fs_empty.yml"); + { + // create empty file + std::ofstream f(fname.c_str(), std::ios::out); + } + + try + { + FileStorage fs(fname, FileStorage::READ); + ADD_FAILURE() << "Exception must be thrown for empty file."; + } + catch (const cv::Exception&) + { + // expected way + // closed files can be checked manually through 'strace' + } + catch (const std::exception& e) + { + ADD_FAILURE() << "Unexpected exception: " << e.what(); + } + catch (...) + { + ADD_FAILURE() << "Unexpected unknown C++ exception"; + } + + EXPECT_EQ(0, remove(fname.c_str())); +} + +TEST(Core_InputOutput, FileStorage_open_empty_16823) +{ + std::string fname = tempfile("test_fs_open_empty.yml"); + { + // create empty file + std::ofstream f(fname.c_str(), std::ios::out); + } + + FileStorage fs; + try + { + fs.open(fname, FileStorage::READ); + ADD_FAILURE() << "Exception must be thrown for empty file."; + } + catch (const cv::Exception&) + { + // expected way + // closed files can be checked manually through 'strace' + } + catch (const std::exception& e) + { + ADD_FAILURE() << "Unexpected exception: " << e.what(); + } + catch (...) + { + ADD_FAILURE() << "Unexpected unknown C++ exception"; + } + + EXPECT_EQ(0, remove(fname.c_str())); +} + }} // namespace