Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #184 Fix Size calculations Fix Stream Size validations #189

Merged
merged 1 commit into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}


}
}