diff --git a/sources/OpenMcdf.Extensions/Properties/AssemblyInfo.cs b/sources/OpenMcdf.Extensions/Properties/AssemblyInfo.cs index ae3b2b34..0263517d 100644 --- a/sources/OpenMcdf.Extensions/Properties/AssemblyInfo.cs +++ b/sources/OpenMcdf.Extensions/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("-")] [assembly: AssemblyProduct("OpenMcdf.Extensions")] -[assembly: AssemblyCopyright("Copyright © Federico Blaseotto, 2023")] +[assembly: AssemblyCopyright("Copyright © Federico Blaseotto, 2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/sources/OpenMcdf/CompoundFile.cs b/sources/OpenMcdf/CompoundFile.cs index af8ff266..aadcc417 100644 --- a/sources/OpenMcdf/CompoundFile.cs +++ b/sources/OpenMcdf/CompoundFile.cs @@ -2269,10 +2269,12 @@ internal void SetStreamLength(CFItem cfItem, long length) int nSec = (int)Math.Floor(((double)(Math.Abs(delta)) / newSectorSize)); //number of sectors to mark as free + int startFreeSector = sectorChain.Count - nSec; // start sector to free + if (newSectorSize == Sector.MINISECTOR_SIZE) - FreeMiniChain(sectorChain, nSec, this.eraseFreeSectors); + FreeMiniChain(sectorChain, startFreeSector, this.eraseFreeSectors); else - FreeChain(sectorChain, nSec, this.eraseFreeSectors); + FreeChain(sectorChain, startFreeSector, this.eraseFreeSectors); } if (sectorChain.Count > 0) diff --git a/sources/OpenMcdf/Properties/AssemblyInfo.cs b/sources/OpenMcdf/Properties/AssemblyInfo.cs index e76a2d35..1c60bdb7 100644 --- a/sources/OpenMcdf/Properties/AssemblyInfo.cs +++ b/sources/OpenMcdf/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Federico Blaseotto")] [assembly: AssemblyProduct("OpenMcdf 2.3")] -[assembly: AssemblyCopyright("Copyright © 2010-2023, Federico Blaseotto")] +[assembly: AssemblyCopyright("Copyright © 2010-2024, Federico Blaseotto")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/sources/Test/OpenMcdf.Test/CFSStreamTest.cs b/sources/Test/OpenMcdf.Test/CFSStreamTest.cs index ac657ec3..c42ecd8d 100644 --- a/sources/Test/OpenMcdf.Test/CFSStreamTest.cs +++ b/sources/Test/OpenMcdf.Test/CFSStreamTest.cs @@ -809,9 +809,12 @@ public void Test_APPEND_DATA_TO_CREATE_LARGE_STREAM() [TestMethod] public void Test_RESIZE_STREAM_NO_TRANSITION() { + int INITIAL_SIZE = 1024 * 1024 * 2; + int DELTA_SIZE = 300; + CompoundFile cf = null; //CFStream st = null; - byte[] b = Helpers.GetBuffer(1024 * 1024 * 2); //2MB buffer + byte[] b = Helpers.GetBuffer(INITIAL_SIZE); //2MB buffer cf = new CompoundFile(CFSVersion.Ver_3, CFSConfiguration.Default); cf.RootStorage.AddStream("AStream").SetData(b); @@ -820,10 +823,22 @@ public void Test_RESIZE_STREAM_NO_TRANSITION() cf = new CompoundFile("$Test_RESIZE_STREAM.cfs", CFSUpdateMode.Update, CFSConfiguration.SectorRecycle); CFStream item = cf.RootStorage.GetStream("AStream"); - item.Resize(item.Size / 2); + item.Resize(INITIAL_SIZE - DELTA_SIZE); //cf.RootStorage.AddStream("BStream").SetData(b); cf.Commit(true); cf.Close(); + + + cf = new CompoundFile("$Test_RESIZE_STREAM.cfs", CFSUpdateMode.ReadOnly, CFSConfiguration.Default); + item = cf.RootStorage.GetStream("AStream"); + Assert.IsTrue(item != null); + Assert.IsTrue(item.Size == INITIAL_SIZE - DELTA_SIZE); + + byte[] buffer = new byte[INITIAL_SIZE - DELTA_SIZE]; + item.Read(buffer, 0, INITIAL_SIZE - DELTA_SIZE); + Assert.IsTrue(Helpers.CompareBuffer(b, buffer, INITIAL_SIZE - DELTA_SIZE)); + cf.Close(); + } [TestMethod] @@ -889,11 +904,13 @@ public void Test_RESIZE_STREAM_TRANSITION_TO_NORMAL() } [TestMethod] - public void Test_RESIZE_MINISTREAM_NO_TRANSITION() + public void Test_RESIZE_MINISTREAM_NO_TRANSITION_MOD() { CompoundFile cf = null; + int INITIAL_SIZE = 1024 * 2; + int SIZE_DELTA = 148; - byte[] b = Helpers.GetBuffer(1024 * 2); + byte[] b = Helpers.GetBuffer(INITIAL_SIZE); cf = new CompoundFile(CFSVersion.Ver_3, CFSConfiguration.Default); cf.RootStorage.AddStream("MiniStream").SetData(b); @@ -902,7 +919,7 @@ public void Test_RESIZE_MINISTREAM_NO_TRANSITION() cf = new CompoundFile("$Test_RESIZE_MINISTREAM.cfs", CFSUpdateMode.Update, CFSConfiguration.SectorRecycle | CFSConfiguration.EraseFreeSectors); CFStream item = cf.RootStorage.GetStream("MiniStream"); - item.Resize(item.Size / 2); + item.Resize(item.Size - SIZE_DELTA); cf.Commit(); cf.Close(); @@ -911,12 +928,12 @@ public void Test_RESIZE_MINISTREAM_NO_TRANSITION() CFStream st = cf.RootStorage.GetStream("MiniStream"); Assert.IsNotNull(st); - Assert.IsTrue(st.Size == 1024); + Assert.IsTrue(st.Size == (INITIAL_SIZE - SIZE_DELTA)); - byte[] buffer = new byte[1024]; - st.Read(buffer, 0, 1024); + byte[] buffer = new byte[INITIAL_SIZE - SIZE_DELTA]; + st.Read(buffer, 0, INITIAL_SIZE - SIZE_DELTA); - Assert.IsTrue(Helpers.CompareBuffer(b, buffer, 1024)); + Assert.IsTrue(Helpers.CompareBuffer(b, buffer, INITIAL_SIZE - SIZE_DELTA)); cf.Close(); } @@ -1116,5 +1133,32 @@ public void Test_CHANGE_STREAM_NAME_FIX_54() } } + /// + /// Resize without transitio to smaller chain has a wrong behaviour + /// + [TestMethod] + public void TEST_RESIZE_STREAM_BUG_119() + { + var cf = new CompoundFile(); + const string DATA = "data"; + var st = cf.RootStorage.AddStream(DATA); + const int size = 10; + var data = Enumerable.Range(0, size).Select(v => (byte)v).ToArray(); + st.SetData(data); + var ms = new MemoryStream(); + cf.Save(ms); + cf.Close(); + + ms.Position = 0; + cf = new CompoundFile(ms, CFSUpdateMode.Update, CFSConfiguration.Default); + st = cf.RootStorage.GetStream(DATA); + byte[] buffer = new byte[size]; + st.Read(buffer, 0, size); + st.Resize(5); // <- can be any number smaller than the current size + st.Write(new byte[] { 0 }, 0); // <- exception here! //NO MORE + cf.Commit(); + cf.Close(); + } + } } diff --git a/sources/Test/OpenMcdf.Test/CFSTorageTest.cs b/sources/Test/OpenMcdf.Test/CFSTorageTest.cs index 8fe65f28..186060a1 100644 --- a/sources/Test/OpenMcdf.Test/CFSTorageTest.cs +++ b/sources/Test/OpenMcdf.Test/CFSTorageTest.cs @@ -457,6 +457,46 @@ public void Test_FIX_BUG_31() } + [TestMethod] + public void Test_FIX_BUG_116() + { + CompoundFile cf = new CompoundFile(); + cf.RootStorage.AddStorage("AStorage") + + .AddStream("AStream") + .SetData(Helpers.GetBuffer(100)); + + cf.SaveAs("Hello$File"); + + cf.Close(); + + CompoundFile cf1 = new CompoundFile("Hello$File", CFSUpdateMode.Update, CFSConfiguration.Default); + + try + { + + cf1.RootStorage.RenameItem("AStorage", "NewStorage"); + cf1.Commit(); + cf1.Close(); + + } + catch (Exception ex) + { + Assert.Fail(ex.Message); + } + + try + { + CompoundFile cf2 = new CompoundFile("Hello$File"); + var st2 = cf2.RootStorage.GetStorage("NewStorage"); + Assert.IsNotNull(st2); + }catch(Exception ex) + { + Assert.Fail($"{ex.Message}"); + } + + } + [TestMethod] [ExpectedException(typeof(OpenMcdf.CFCorruptedFileException))] public void Test_CORRUPTEDDOC_BUG36_SHOULD_THROW_CORRUPTED_FILE_EXCEPTION() diff --git a/sources/Test/OpenMcdf.Test/Helpers.cs b/sources/Test/OpenMcdf.Test/Helpers.cs index b0de1422..d802dbf9 100644 --- a/sources/Test/OpenMcdf.Test/Helpers.cs +++ b/sources/Test/OpenMcdf.Test/Helpers.cs @@ -14,6 +14,7 @@ public static byte[] GetBuffer(int count) r.NextBytes(b); return b; } + public static void FillBufferWithRandomData(byte[] buffer) { Random r = new Random();