Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit988dec4

Browse files
Handle range lock sector
1 parent15011f1 commit988dec4

File tree

8 files changed

+78
-20
lines changed

8 files changed

+78
-20
lines changed

‎OpenMcdf.Tests/RootStorageTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,4 +252,28 @@ public void V3ThrowsIOExceptionAt2GB()
252252

253253
Assert.ThrowsException<IOException>(()=>stream.Write(buffer,0,buffer.Length));
254254
}
255+
256+
[TestMethod]
257+
[DoNotParallelize]// High memory usage
258+
publicvoidValidateRangeLockSector()
259+
{
260+
RecyclableMemoryStreamManagermanager=new();
261+
usingRecyclableMemoryStreambaseStream=new(manager);
262+
baseStream.Capacity64=RootContext.RangeLockSectorOffset;
263+
264+
usingvarrootStorage=RootStorage.Create(baseStream,Version.V4);
265+
using(CfbStreamstream=rootStorage.CreateStream("Test"))
266+
{
267+
byte[]buffer=TestData.CreateByteArray(4096);
268+
while(baseStream.Length<=RootContext.RangeLockSectorOffset)
269+
stream.Write(buffer,0,buffer.Length);
270+
}
271+
272+
Assert.IsTrue(rootStorage.Validate());
273+
274+
rootStorage.Delete("Test");
275+
rootStorage.Flush();
276+
277+
Assert.IsTrue(rootStorage.Validate());
278+
}
255279
}

‎OpenMcdf/Fat.cs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,20 @@ internal sealed class Fat : ContextBase, IEnumerable<FatEntry>, IDisposable
1515
SectorcachedSector=Sector.EndOfChain;
1616
privateboolisDirty;
1717

18+
publicFunc<FatEntry,bool>IsUsed{get;}
19+
1820
publicFat(RootContextSiterootContextSite)
1921
:base(rootContextSite)
2022
{
2123
fatSectorEnumerator=new(rootContextSite);
2224
cachedSectorBuffer=newbyte[Context.SectorSize];
25+
26+
if(Context.Version==Version.V3)
27+
IsUsed= entry=>entry.Valueis notSectorType.Free;
28+
elseif(Context.Version==Version.V4)
29+
IsUsed= entry=>entry.Valueis notSectorType.Free&&entry.Indexis notRootContext.RangeLockSectorId;
30+
else
31+
thrownewNotSupportedException($"Unsupported major version:{Context.Version}.");
2332
}
2433

2534
publicvoidDispose()
@@ -143,14 +152,14 @@ public uint Add(FatEnumerator fatEnumerator, uint startIndex)
143152

144153
publicSectorGetLastUsedSector()
145154
{
146-
uintlastUsedSectorIndex=uint.MaxValue;
155+
FatEntrylastUsedSectorIndex=new(uint.MaxValue,uint.MaxValue);
147156
foreach(FatEntryentryinthis)
148157
{
149-
if(!entry.IsFree)
150-
lastUsedSectorIndex=entry.Index;
158+
if(IsUsed(entry))
159+
lastUsedSectorIndex=entry;
151160
}
152161

153-
returnnew(lastUsedSectorIndex,Context.SectorSize);
162+
returnnew(lastUsedSectorIndex.Index,Context.SectorSize);
154163
}
155164

156165
publicIEnumerator<FatEntry>GetEnumerator()=>newFatEnumerator(Context.Fat);
@@ -172,7 +181,7 @@ internal void WriteTrace(TextWriter writer)
172181
foreach(FatEntryentryinthis)
173182
{
174183
Sectorsector=new(entry.Index,Context.SectorSize);
175-
if(entry.IsFree)
184+
if(entry.ValueisSectorType.Free)
176185
{
177186
freeCount++;
178187
writer.WriteLine($"{entry}");
@@ -194,7 +203,7 @@ internal void WriteTrace(TextWriter writer)
194203
}
195204

196205
[ExcludeFromCodeCoverage]
197-
internalvoidValidate()
206+
internalboolValidate()
198207
{
199208
longfatSectorCount=0;
200209
longdifatSectorCount=0;
@@ -213,8 +222,21 @@ internal void Validate()
213222
thrownewFileFormatException($"FAT sector count mismatch. Expected:{Context.Header.FatSectorCount} Actual:{fatSectorCount}.");
214223
if(Context.Header.DifatSectorCount!=difatSectorCount)
215224
thrownewFileFormatException($"DIFAT sector count mismatch: Expected:{Context.Header.DifatSectorCount} Actual:{difatSectorCount}.");
225+
226+
if(Context.Length<RootContext.RangeLockSectorOffset)
227+
{
228+
if(this.TryGetValue(RootContext.RangeLockSectorId,outuintvalue)&&value!=SectorType.Free)
229+
thrownewFileFormatException($"Range lock FAT entry is not free.");
230+
}
231+
else
232+
{
233+
if(this[RootContext.RangeLockSectorId]!=SectorType.EndOfChain)
234+
thrownewFileFormatException($"Range lock sector is not at the end of the chain.");
235+
}
236+
237+
returntrue;
216238
}
217239

218240
[ExcludeFromCodeCoverage]
219-
internallongGetFreeSectorCount()=>this.Count(entry=>entry.IsFree);
241+
internallongGetFreeSectorCount()=>this.Count(entry=>entry.Value==SectorType.Free);
220242
}

‎OpenMcdf/FatEntry.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ namespace OpenMcdf;
77
/// </summary>
88
internalrecordstructFatEntry(uintIndex,uintValue)
99
{
10-
publicreadonlyboolIsFree=>Value==SectorType.Free;
11-
1210
[ExcludeFromCodeCoverage]
1311
publicoverridereadonlystringToString()=>$"#{Index}:{Value}";
1412
}

‎OpenMcdf/FatEnumerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public bool MoveNextFreeEntry()
7777
{
7878
while(MoveNext())
7979
{
80-
if(value==SectorType.Free)
80+
if(valueisSectorType.Free)
8181
returntrue;
8282
}
8383

‎OpenMcdf/FatStream.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespaceOpenMcdf;
1+
usingSystem.Diagnostics;
2+
3+
namespaceOpenMcdf;
24

35
/// <summary>
46
/// Provides a <inheritdoc cref="Stream"/> for a stream object in a compound file./>
@@ -185,6 +187,7 @@ public override void Write(byte[] buffer, int offset, int count)
185187
longwriteLength=Math.Min(remaining,sector.Length-sectorOffset);
186188
writer.Write(buffer,localOffset,(int)writeLength);
187189
Context.ExtendStreamLength(sector.EndPosition);
190+
Debug.Assert(Context.Length>=Context.Stream.Length);
188191
position+=writeLength;
189192
writeCount+=(int)writeLength;
190193
sectorOffset=0;

‎OpenMcdf/MiniFat.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public uint Add(MiniFatEnumerator miniFatEnumerator, uint startIndex)
133133
FatEntryentry=miniFatEnumerator.Current;
134134
this[entry.Index]=SectorType.EndOfChain;
135135

136-
Debug.Assert(entry.IsFree);
136+
Debug.Assert(entry.ValueisSectorType.Free);
137137
MiniSectorminiSector=new(entry.Index,Context.MiniSectorSize);
138138
if(Context.MiniStream.Length<miniSector.EndPosition)
139139
Context.MiniStream.SetLength(miniSector.EndPosition);
@@ -153,7 +153,7 @@ internal void WriteTrace(TextWriter writer)
153153
}
154154

155155
[ExcludeFromCodeCoverage]
156-
internalvoidValidate()
156+
internalboolValidate()
157157
{
158158
usingMiniFatEnumeratorminiFatEnumerator=new(ContextSite);
159159

@@ -165,5 +165,7 @@ internal void Validate()
165165
thrownewFileFormatException($"Mini FAT entry{current} is beyond the end of the mini stream.");
166166
}
167167
}
168+
169+
returntrue;
168170
}
169171
}

‎OpenMcdf/RootContext.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ enum IOContextFlags
1616
/// </summary>
1717
internalsealedclassRootContext:ContextBase,IDisposable
1818
{
19-
constlongMaximumV3StreamLength=2147483648;
19+
internalconstlongMaximumV3StreamLength=2147483648;
20+
internalconstuintRangeLockSectorOffset=0x7FFFFF00;
21+
internalconstuintRangeLockSectorId=RangeLockSectorOffset/(1<<Header.SectorShiftV4)-1;
2022

2123
readonlyIOContextFlagscontextFlags;
2224
readonlyCfbBinaryWriter?writer;
@@ -187,11 +189,14 @@ public void Flush()
187189

188190
publicvoidExtendStreamLength(longlength)
189191
{
192+
if(Length>=length)
193+
return;
194+
190195
if(VersionisVersion.V3&&length>MaximumV3StreamLength)
191196
thrownewIOException("V3 compound files are limited to 2 GB.");
192-
193-
if(Length<length)
194-
Length=length;
197+
elseif(VersionisVersion.V4&&Length<RangeLockSectorOffset&&length>=RangeLockSectorOffset)
198+
Fat[RangeLockSectorId]=SectorType.EndOfChain;
199+
Length=length;
195200
}
196201

197202
voidTrimBaseStream()
@@ -200,6 +205,9 @@ void TrimBaseStream()
200205
if(!lastUsedSector.IsValid)
201206
thrownewFileFormatException("Last used sector is invalid");
202207

208+
if(VersionisVersion.V4&&lastUsedSector.EndPosition<RangeLockSectorOffset)
209+
Fat.TrySetValue(RangeLockSectorId,SectorType.Free);
210+
203211
Length=lastUsedSector.EndPosition;
204212
BaseStream.SetLength(Length);
205213
}

‎OpenMcdf/RootStorage.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,11 @@ internal void Trace(TextWriter writer)
244244
Context.MiniFat.WriteTrace(writer);
245245
}
246246

247+
// TODO: Move checks to Tests project as Asserts
247248
[ExcludeFromCodeCoverage]
248-
internalvoidValidate()
249+
internalboolValidate()
249250
{
250-
Context.Fat.Validate();
251-
Context.MiniFat.Validate();
251+
returnContext.Fat.Validate()
252+
&&Context.MiniFat.Validate();
252253
}
253254
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp