Skip to content

Commit

Permalink
Merge pull request #189 from ironfede/pr/fix-184
Browse files Browse the repository at this point in the history
Fix #184 Fix Size calculations Fix Stream Size validations
  • Loading branch information
ironfede authored Oct 10, 2024
2 parents 01f1904 + 3eb817c commit ceb409e
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 31 deletions.
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ csharp_style_prefer_pattern_matching = true
csharp_style_prefer_switch_expression = true

# Null-checking preferences
csharp_style_conditional_delegate_call = true
csharp_style_conditional_delegate_call = true:suggestion

# Modifier preferences
csharp_prefer_static_anonymous_function = true
Expand Down Expand Up @@ -188,7 +188,7 @@ csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = ignore
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
Expand Down
81 changes: 52 additions & 29 deletions sources/OpenMcdf/CompoundFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,8 @@ List<Sector> miniStream
null,
sourceStream);



// Set updated/new sectors within the ministream
// We are writing data in a NORMAL Sector chain.
for (int i = 0; i < sectorChain.Count; i++)
Expand All @@ -743,9 +745,13 @@ List<Sector> miniStream
s.Id = (int)(miniStreamView.Position - Sector.MINISECTOR_SIZE) / Sector.MINISECTOR_SIZE;

RootStorage.DirEntry.Size = miniStreamView.Length;


}
}



// Update miniFAT
StreamRW miniFATStreamRW = new(miniFATView);
for (int i = 0; i < sectorChain.Count - 1; i++)
Expand All @@ -754,12 +760,14 @@ List<Sector> miniStream
int nextId = sectorChain[i + 1].Id;
miniFATStreamRW.Seek(currentId * 4, SeekOrigin.Begin);
miniFATStreamRW.Write(nextId);

}

// Write End of Chain in MiniFAT
miniFATStreamRW.Seek(sectorChain[sectorChain.Count - 1].Id * SIZE_OF_SID, SeekOrigin.Begin);
miniFATStreamRW.Write(Sector.ENDOFCHAIN);


// Update sector chains
AllocateSectorChain(miniStreamView.BaseSectorChain);
AllocateSectorChain(miniFATView.BaseSectorChain);
Expand Down Expand Up @@ -1007,6 +1015,10 @@ private void AllocateFATSectorChain(List<Sector> sectorChain)
/// <param name="FATsectorChain">A FAT sector chain</param>
private void AllocateDIFATSectorChain(List<Sector> FATsectorChain)
{
//Get initial DIFAT chain
List<Sector> difatSectors =
GetSectorChain(-1, SectorType.DIFAT);

// Get initial sector's count
header.FATSectorsNumber = FATsectorChain.Count;

Expand All @@ -1022,22 +1034,34 @@ private void AllocateDIFATSectorChain(List<Sector> FATsectorChain)
}

// Sector count...
int nCurrentSectors = sectors.Count;
//int nCurrentSectors = sectors.Count;

// Temp DIFAT count
int nDIFATSectors = (int)header.DIFATSectorsNumber;
//int nDIFATSectors = (int)header.DIFATSectorsNumber;
int nDIFATSectors = 0;

if (FATsectorChain.Count > HEADER_DIFAT_ENTRIES_COUNT)
{
nDIFATSectors = Ceiling((double)(FATsectorChain.Count - HEADER_DIFAT_ENTRIES_COUNT) / DIFAT_SECTOR_FAT_ENTRIES_COUNT);
nDIFATSectors = LowSaturation(nDIFATSectors - (int)header.DIFATSectorsNumber); //required DIFAT
}


for (int i = 0; i < (nDIFATSectors - difatSectors.Count); i++)
{
Sector s = new Sector(SectorSize, sourceStream);
sectors.Add(s);
s.Id = sectors.Count - 1;
s.Type = SectorType.DIFAT;
difatSectors.Add(s);
}

// ...sum with new required DIFAT sectors count
nCurrentSectors += nDIFATSectors;
//nCurrentSectors += nDIFATSectors;
//header.FATSectorsNumber += nDIFATSectors;

// ReCheck FAT bias
while (header.FATSectorsNumber * FAT_SECTOR_ENTRIES_COUNT < nCurrentSectors)
while (FATsectorChain.Count * FAT_SECTOR_ENTRIES_COUNT < sectors.Count)
{
Sector extraFATSector = new Sector(SectorSize, sourceStream);
sectors.Add(extraFATSector);
Expand All @@ -1047,26 +1071,25 @@ private void AllocateDIFATSectorChain(List<Sector> FATsectorChain)

FATsectorChain.Add(extraFATSector);

header.FATSectorsNumber++;
nCurrentSectors++;
//header.FATSectorsNumber++;
//nCurrentSectors++;

//... so, adding a FAT sector may induce DIFAT sectors to increase by one
// and consequently this may induce ANOTHER FAT sector (TO-THINK: May this condition occur ?)
if (nDIFATSectors * DIFAT_SECTOR_FAT_ENTRIES_COUNT <
(header.FATSectorsNumber > HEADER_DIFAT_ENTRIES_COUNT ?
header.FATSectorsNumber - HEADER_DIFAT_ENTRIES_COUNT :
0))
if (difatSectors.Count * DIFAT_SECTOR_FAT_ENTRIES_COUNT < (FATsectorChain.Count - HEADER_DIFAT_ENTRIES_COUNT))
{
nDIFATSectors++;
nCurrentSectors++;

Sector s = new Sector(SectorSize, sourceStream);
sectors.Add(s);
s.Type = SectorType.DIFAT;
s.Id = sectors.Count - 1;
difatSectors.Add(s);

}
}

List<Sector> difatSectors =
GetSectorChain(-1, SectorType.DIFAT);

using StreamView difatStream
= new StreamView(difatSectors, SectorSize, sourceStream);
= new StreamView(difatSectors, SectorSize, difatSectors.Count * SectorSize, null, sourceStream);

StreamRW difatStreamRW = new(difatStream);

Expand Down Expand Up @@ -1101,7 +1124,7 @@ private void AllocateDIFATSectorChain(List<Sector> FATsectorChain)
}
}

header.DIFATSectorsNumber = (uint)nDIFATSectors;
header.DIFATSectorsNumber = (uint)difatStream.BaseSectorChain.Count;

// Chain first sector
if (difatStream.BaseSectorChain != null && difatStream.BaseSectorChain.Count > 0)
Expand Down Expand Up @@ -1130,16 +1153,17 @@ private void AllocateDIFATSectorChain(List<Sector> FATsectorChain)

// Mark DIFAT Sectors in FAT
using StreamView fatSv =
new StreamView(FATsectorChain, SectorSize, header.FATSectorsNumber * SectorSize, null, sourceStream);
new StreamView(FATsectorChain, SectorSize, FATsectorChain.Count * SectorSize, null, sourceStream);

StreamRW streamRW = new(fatSv);
for (int i = 0; i < header.DIFATSectorsNumber; i++)

for (int i = 0; i < difatStream.BaseSectorChain.Count; i++)
{
streamRW.Seek(difatStream.BaseSectorChain[i].Id * 4, SeekOrigin.Begin);
streamRW.Write(Sector.DIFSECT);
}

for (int i = 0; i < header.FATSectorsNumber; i++)
for (int i = 0; i < fatSv.BaseSectorChain.Count; i++)
{
streamRW.Seek(fatSv.BaseSectorChain[i].Id * 4, SeekOrigin.Begin);
streamRW.Write(Sector.FATSECT);
Expand All @@ -1148,7 +1172,8 @@ private void AllocateDIFATSectorChain(List<Sector> FATsectorChain)
//fatSv.Seek(fatSv.BaseSectorChain[fatSv.BaseSectorChain.Count - 1].Id * 4, SeekOrigin.Begin);
//fatSv.Write(BitConverter.GetBytes(Sector.ENDOFCHAIN), 0, 4);

header.FATSectorsNumber = fatSv.BaseSectorChain.Count;
header.FATSectorsNumber = FATsectorChain.Count;
header.DIFATSectorsNumber = (uint)difatSectors.Count;
}

/// <summary>
Expand Down Expand Up @@ -1244,9 +1269,8 @@ List<Sector> result
List<Sector> difatSectors = GetDifatSectorChain();

int idx = 0;


int nextSecID;

// Read FAT entries from the header Fat entry array (max 109 entries)
while (idx < header.FATSectorsNumber && idx < N_HEADER_FAT_ENTRY)
{
Expand Down Expand Up @@ -1277,9 +1301,7 @@ List<Sector> result
(
difatSectors,
SectorSize,
header.FATSectorsNumber > N_HEADER_FAT_ENTRY ?
(header.FATSectorsNumber - N_HEADER_FAT_ENTRY) * 4 :
0,
difatSectors.Count * SectorSize,
null,
sourceStream);

Expand Down Expand Up @@ -1340,6 +1362,7 @@ List<Sector> result
using StreamView fatStream
= new StreamView(fatSectors, SectorSize, fatSectors.Count * SectorSize, null, sourceStream);
StreamRW fatStreamRW = new(fatStream);

while (true)
{
if (nextSecID == Sector.ENDOFCHAIN) break;
Expand Down Expand Up @@ -1389,12 +1412,12 @@ List<Sector> result
List<Sector> miniStream = GetNormalSectorChain(RootEntry.StartSect);

using StreamView miniFATView
= new StreamView(miniFAT, SectorSize, header.MiniFATSectorsNumber * Sector.MINISECTOR_SIZE, null, sourceStream);
= new StreamView(miniFAT, SectorSize, header.MiniFATSectorsNumber * SectorSize, null, sourceStream);

using StreamView miniStreamView =
new StreamView(miniStream, SectorSize, RootStorage.Size, null, sourceStream);

using BinaryReader miniFATReader = new BinaryReader(miniFATView);
StreamRW miniFATReader = new StreamRW(miniFATView);

int nextSecID = secID;
HashSet<int> processedSectors = new HashSet<int>();
Expand Down Expand Up @@ -1834,7 +1857,7 @@ List<Sector> miniFAT
= GetSectorChain(header.FirstMiniFATSectorID, SectorType.Normal);

using StreamView miniFATView
= new StreamView(miniFAT, SectorSize, header.MiniFATSectorsNumber * Sector.MINISECTOR_SIZE, null, sourceStream);
= new StreamView(miniFAT, SectorSize, header.MiniFATSectorsNumber * SectorSize, null, sourceStream);

StreamRW miniFATStreamRW = new(miniFATView);

Expand Down
3 changes: 3 additions & 0 deletions sources/OpenMcdf/StreamView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ public override int Read(byte[] buffer, int offset, int count)
long intMax = Math.Min(int.MaxValue, length);
count = Math.Min((int)intMax, count);

// Ensure read request greater then stream length, when position is not 0, return only the limited and correct number of bytes
count = (int)Math.Min(length - position, count);

if (BaseSectorChain != null && BaseSectorChain.Count > 0)
{
// First sector
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,5 +472,27 @@ public void Test_Retain_Dictionary_Property_In_AppSpecific_Streams()
CollectionAssert.AreEqual(expectedPropertyNames, co.PropertyNames);
}
}

[TestMethod]
public void Test_FIX_CRASH()
{
using CompoundFile cf = new(CFSVersion.Ver_4, CFSConfiguration.Default);

CFStream cfStream = cf.RootStorage.AddStream("MyStream");
using Stream stream = cfStream.AsIOStream();
const int BufferLength = 4096 * 21;
var buffer = Helpers.GetBuffer(BufferLength);
stream.Write(buffer, 0, buffer.Length);
stream.Position = 0;

Assert.AreEqual(BufferLength, cfStream.Size);

using MemoryStream memoryStream = new();
using BufferedStream bufferedStream = new(stream);
bufferedStream.CopyTo(memoryStream);

Assert.AreEqual(memoryStream.Length, cfStream.Size);

}
}
}
2 changes: 2 additions & 0 deletions sources/Test/OpenMcdf.Test/CompoundFileTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,5 +1088,7 @@ public void Test_FIX_BUG_96_CompoundFile_SaveOverwrite()

File.Delete(filename2);
}


}
}

0 comments on commit ceb409e

Please sign in to comment.