diff --git a/src/core/src/pass/serialize.cpp b/src/core/src/pass/serialize.cpp index f179630b155d22..baffb99ce79775 100644 --- a/src/core/src/pass/serialize.cpp +++ b/src/core/src/pass/serialize.cpp @@ -1268,15 +1268,21 @@ bool pass::Serialize::run_on_model(const std::shared_ptr& model) { if (xmlDir != xmlPath_ref) ov::util::create_directory_recursive(xmlDir); - std::ofstream bin_file(binPath_ref, std::ios::out | std::ios::binary); - OPENVINO_ASSERT(bin_file, message_bin); - - // create xml file - std::ofstream xml_file(xmlPath_ref, std::ios::out); - OPENVINO_ASSERT(xml_file, message_xml); - try { + // create bin file + std::ofstream bin_file; + bin_file.exceptions(std::ofstream::failbit | std::ofstream::badbit); + bin_file.open(m_binPath, std::ios::out | std::ios::binary); + OPENVINO_ASSERT(bin_file, "Can't open bin file: \"" + m_binPath + "\""); + + // create xml file + std::ofstream xml_file; + xml_file.exceptions(std::ofstream::failbit | std::ofstream::badbit); + xml_file.open(m_xmlPath, std::ios::out | std::ios::binary); + OPENVINO_ASSERT(xml_file, "Can't open xml file: \"" + m_xmlPath + "\""); + serializeFunc(xml_file, bin_file, model, m_version); + } catch (const ov::AssertFailure&) { // optimization decision was made to create .bin file upfront and // write to it directly instead of buffering its content in memory, @@ -1285,6 +1291,7 @@ bool pass::Serialize::run_on_model(const std::shared_ptr& model) { bin_file.close(); std::ignore = std::remove(m_xmlPath.c_str()); std::ignore = std::remove(m_binPath.c_str()); + throw; } } diff --git a/src/core/tests/pass/serialization/serialize.cpp b/src/core/tests/pass/serialization/serialize.cpp index e45d5d1d1434ff..fb7b9729a8589b 100644 --- a/src/core/tests/pass/serialization/serialize.cpp +++ b/src/core/tests/pass/serialization/serialize.cpp @@ -14,6 +14,27 @@ #include "openvino/util/file_util.hpp" #include "read_ir.hpp" +#ifdef _WIN32 +# include +#else +# include +#endif + +namespace { +bool createReadOnlyFile(const std::string& filename) { + std::ofstream file(filename); + if (file.is_open()) { + file.close(); +#ifdef _WIN32 + return SetFileAttributes(filename.c_str(), FILE_ATTRIBUTE_READONLY) != 0; +#else + return chmod(filename.c_str(), S_IRUSR) == 0; // Set file as read-only for owner +#endif + } + return false; +} +} // namespace + using SerializationParams = std::tuple; class SerializationTest : public ov::test::TestsCommon, public testing::WithParamInterface { @@ -56,6 +77,24 @@ class SerializationTest : public ov::test::TestsCommon, public testing::WithPara } }; +TEST(SerializationTest, WriteInReadOnly) { + // Create read-only files + ASSERT_TRUE(createReadOnlyFile(m_out_xml_path)); + ASSERT_TRUE(createReadOnlyFile(m_out_bin_path)); + + // Set up the serializer with the current paths + ov::pass::Serialize serializer(m_out_xml_path, m_out_bin_path); + + auto m = std::make_shared(ov::OutputVector{}, ov::ParameterVector{}, ""); + + // Expect that running the serializer on a read-only file throws an exception + EXPECT_THROW(serializer.run_on_model(m), ov::AssertFailure); + + // Confirm that files were not successfully written. + ASSERT_FALSE(std::ifstream(m_out_xml_path).good()); + ASSERT_FALSE(std::ifstream(m_out_bin_path).good()); +} + TEST_P(SerializationTest, CompareFunctions) { CompareSerialized([this](const std::shared_ptr& m) { ov::pass::Serialize(m_out_xml_path, m_out_bin_path).run_on_model(m);