diff --git a/core/libs/nid/src/main.cpp b/core/libs/nid/src/main.cpp index 7e459dc99d12..722c765e7cd0 100644 --- a/core/libs/nid/src/main.cpp +++ b/core/libs/nid/src/main.cpp @@ -19,6 +19,8 @@ void _writeFile(const std::string& path, const std::vector& data) std::ofstream f(Nid::Internal::NativePath(path), std::ios::binary); if (!f) throw std::runtime_error("cannot write: " + path); f.write(reinterpret_cast(data.data()), static_cast(data.size())); + f.close(); + if (!f) throw std::runtime_error("cannot write: " + path); } } diff --git a/core/libs/nid/tests/test_native_paths.py b/core/libs/nid/tests/test_native_paths.py index 5a08185bc0d7..ccfd9e6b8cb1 100644 --- a/core/libs/nid/tests/test_native_paths.py +++ b/core/libs/nid/tests/test_native_paths.py @@ -1,4 +1,5 @@ import subprocess +import signal import sys import tempfile import unittest @@ -6,6 +7,11 @@ from test_macho_nids import build_dylib, exports_of, nid +try: + import resource +except ImportError: + resource = None + PATCHER = Path(sys.argv.pop(1)).resolve() @@ -51,6 +57,27 @@ def test_missing_unicode_input_does_not_modify_another_file(self): self.assertFalse(missing.exists()) self.assertEqual(existing.read_bytes(), b"unchanged") + @unittest.skipUnless(resource is not None and hasattr(signal, "SIGXFSZ"), "requires POSIX file size limits") + def test_failed_file_write_is_reported_without_success(self): + for limit in (0, 1024): + with self.subTest(limit=limit), tempfile.TemporaryDirectory() as temporary: + file = Path(temporary) / "library.prx" + original = build_dylib([("_puts_nid_postfix", 0, 0x100)], []) + file.write_bytes(original) + + def restrict_output(): + signal.signal(signal.SIGXFSZ, signal.SIG_IGN) + resource.setrlimit(resource.RLIMIT_FSIZE, (limit, limit)) + + result = subprocess.run([str(PATCHER), "libtest", str(file)], capture_output=True, + encoding="utf-8", errors="replace", timeout=10, + preexec_fn=restrict_output) + self.assertEqual(file.stat().st_size, limit) + self.assertEqual(result.returncode, 2, result.stdout + result.stderr) + self.assertIn("cannot write", result.stderr) + self.assertIn(str(file), result.stderr) + self.assertNotIn("OK:", result.stdout) + if __name__ == "__main__": unittest.main()