Skip to content

Commit

Permalink
Added protection for compound files with cyclic fat structure. Addres…
Browse files Browse the repository at this point in the history
  • Loading branch information
Henning Krause committed Jan 22, 2019
1 parent de2da8f commit de52b97
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 10 deletions.
31 changes: 23 additions & 8 deletions sources/OpenMcdf/CompoundFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,8 @@ List<Sector> result
int nextSecID
= Sector.ENDOFCHAIN;

HashSet<int> processedSectors = new HashSet<int>();

if (header.DIFATSectorsNumber != 0)
{
validationCount = (int)header.DIFATSectorsNumber;
Expand All @@ -1290,6 +1292,7 @@ int nextSecID
while (true && validationCount >= 0)
{
nextSecID = BitConverter.ToInt32(s.GetData(), GetSectorSize() - 4);
EnsureUniqueSectorIndex(nextSecID, processedSectors);

// Strictly speaking, the following condition is not correct from
// a specification point of view:
Expand Down Expand Up @@ -1321,6 +1324,16 @@ int nextSecID
return result;
}

private static void EnsureUniqueSectorIndex(int nextSecID, HashSet<int> processedSectors)
{
if (processedSectors.Contains(nextSecID))
{
throw new CFCorruptedFileException("The file is corrupted.");
}

processedSectors.Add(nextSecID);
}

/// <summary>
/// Get the FAT sector chain
/// </summary>
Expand Down Expand Up @@ -1361,6 +1374,7 @@ int nextSecID
//Is there any DIFAT sector containing other FAT entries ?
if (difatSectors.Count > 0)
{
HashSet<int> processedSectors = new HashSet<int>();
StreamView difatStream
= new StreamView
(
Expand Down Expand Up @@ -1404,6 +1418,7 @@ StreamView difatStream

difatStream.Read(nextDIFATSectorBuffer, 0, 4);
nextSecID = BitConverter.ToInt32(nextDIFATSectorBuffer, 0);
EnsureUniqueSectorIndex(nextSecID, processedSectors);
nFat++;
}
}
Expand All @@ -1425,6 +1440,7 @@ List<Sector> result
int nextSecID = secID;

List<Sector> fatSectors = GetFatSectorChain();
HashSet<int> processedSectors = new HashSet<int>();

StreamView fatStream
= new StreamView(fatSectors, GetSectorSize(), fatSectors.Count * GetSectorSize(), null, sourceStream);
Expand Down Expand Up @@ -1453,10 +1469,9 @@ StreamView fatStream
fatStream.Seek(nextSecID * 4, SeekOrigin.Begin);
int next = fatStream.ReadInt32();

if (next != nextSecID)
nextSecID = next;
else
throw new CFCorruptedFileException("Cyclic sector chain found. File is corrupted");
EnsureUniqueSectorIndex(next, processedSectors);
nextSecID = next;

}


Expand Down Expand Up @@ -1490,6 +1505,8 @@ StreamView miniFATView

nextSecID = secID;

HashSet<int> processedSectors = new HashSet<int>();

while (true)
{
if (nextSecID == Sector.ENDOFCHAIN)
Expand All @@ -1509,10 +1526,8 @@ StreamView miniFATView
miniFATView.Seek(nextSecID * 4, SeekOrigin.Begin);
int next = miniFATReader.ReadInt32();

if (next != nextSecID)
nextSecID = next;
else
throw new CFCorruptedFileException("Cyclic sector chain found. File is corrupted");
nextSecID = next;
EnsureUniqueSectorIndex(nextSecID, processedSectors);
}
}
return result;
Expand Down
2 changes: 2 additions & 0 deletions sources/OpenMcdf/StreamView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ public override int Read(byte[] buffer, int offset, int count)

if (nToRead != 0)
{
if (secIndex > sectorChain.Count) throw new CFCorruptedFileException("The file is probably corrupted.");

Buffer.BlockCopy(
sectorChain[secIndex].GetData(),
0,
Expand Down
27 changes: 27 additions & 0 deletions sources/Test/OpenMcdf.Test/CompoundFileTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,33 @@ public void Test_FIX_GH_38_B()
}
}

[TestMethod]
[ExpectedException(typeof(CFCorruptedFileException))]
public void Test_CorruptedSectorChain_Doc()
{
var f = new CompoundFile("corrupted-sector-chain.doc");

f.Close();
}

[TestMethod]
[ExpectedException(typeof(CFCorruptedFileException))]
public void Test_CorruptedSectorChain_Cfs()
{
var f = new CompoundFile("corrupted-sector-chain.cfs");

f.Close();
}

[TestMethod]
[ExpectedException(typeof(CFCorruptedFileException))]
public void Test_CorruptedSectorChain_Doc2()
{
var f = new CompoundFile("corrupted-sector-chain-2.doc");

f.Close();
}

//[TestMethod]
//public void Test_CORRUPTED_CYCLIC_DIFAT_VALIDATION_CHECK()
//{
Expand Down
4 changes: 2 additions & 2 deletions sources/Test/OpenMcdf.Test/SectorCollectionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public void ItemTest()
}
catch (Exception ex)
{
Assert.IsTrue(ex is ArgumentOutOfRangeException);
Assert.IsTrue(ex is CFException);
}

try
Expand All @@ -130,7 +130,7 @@ public void ItemTest()
}
catch (Exception ex)
{
Assert.IsTrue(ex is ArgumentOutOfRangeException);
Assert.IsTrue(ex is CFException);
}
}

Expand Down
Binary file not shown.
Binary file not shown.
Binary file added sources/Test/TestFiles/corrupted-sector-chain.doc
Binary file not shown.

0 comments on commit de52b97

Please sign in to comment.