Skip to content

Commit

Permalink
Detect mini FAT cycles with Floyds' algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-visionaid committed Nov 20, 2024
1 parent c5ed58e commit 9efa549
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions OpenMcdf/MiniFatChainEnumerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal sealed class MiniFatChainEnumerator : ContextBase, IEnumerator<uint>
uint index = uint.MaxValue;
private uint current = uint.MaxValue;
private long length = -1;
private uint slow = uint.MaxValue; // Floyd's cycle-finding algorithm

public MiniFatChainEnumerator(RootContextSite rootContextSite, uint startSectorId)
: base(rootContextSite)
Expand Down Expand Up @@ -60,8 +61,8 @@ public bool MoveNext()
}
else if (!SectorType.IsFreeOrEndOfChain(current))
{
uint sectorId = Context.MiniFat[current];
if (sectorId == SectorType.EndOfChain)
uint value = Context.MiniFat[current];
if (value == SectorType.EndOfChain)
{
index = uint.MaxValue;
current = uint.MaxValue;
Expand All @@ -70,10 +71,18 @@ public bool MoveNext()

uint nextIndex = index + 1;
if (nextIndex > SectorType.Maximum)
throw new FileFormatException("Mini FAT chain is corrupt.");
throw new FileFormatException("Mini FAT chain length is greater than the maximum.");

if (nextIndex % 2 == 0 && !SectorType.IsFreeOrEndOfChain(slow))
{
// Slow might become free or end of chain while shrinking
slow = Context.MiniFat[slow];
if (slow == value)
throw new FileFormatException("Mini FAT chain contains a loop.");
}

index = nextIndex;
current = sectorId;
current = value;
return true;
}

Expand Down Expand Up @@ -203,6 +212,7 @@ public void Reset()
start = true;
index = uint.MaxValue;
current = uint.MaxValue;
slow = uint.MaxValue;
}

[ExcludeFromCodeCoverage]
Expand Down

0 comments on commit 9efa549

Please sign in to comment.