Skip to content

Commit

Permalink
Limit V3 compund files to 2 GB
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-visionaid committed Dec 5, 2024
1 parent 6c4c5df commit 99455c9
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 1 deletion.
1 change: 1 addition & 0 deletions OpenMcdf.Tests/OpenMcdf.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="MSTest" />
</ItemGroup>
Expand Down
23 changes: 22 additions & 1 deletion OpenMcdf.Tests/RootStorageTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace OpenMcdf.Tests;
using Microsoft.IO;

namespace OpenMcdf.Tests;

[TestClass]
public sealed class RootStorageTests
Expand Down Expand Up @@ -231,4 +233,23 @@ public void DeleteTrimsBaseStream(bool consolidate)

Assert.IsTrue(originalLength > newLength);
}

[TestMethod]
[DoNotParallelize] // High memory usage
public void V3ThrowsIOExceptionAt2GB()
{
const long MaxStreamLength = 2L * 1024 * 1024 * 1024;

RecyclableMemoryStreamManager manager = new();
using RecyclableMemoryStream baseStream = new(manager);
baseStream.Capacity64 = MaxStreamLength;

using var rootStorage = RootStorage.Create(baseStream, Version.V3);
using CfbStream stream = rootStorage.CreateStream("Test");
byte[] buffer = TestData.CreateByteArray(1024 * 1024);
while (baseStream.Length + buffer.Length <= MaxStreamLength)
stream.Write(buffer, 0, buffer.Length);

Assert.ThrowsException<IOException>(() => stream.Write(buffer, 0, buffer.Length));
}
}
5 changes: 5 additions & 0 deletions OpenMcdf/RootContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ enum IOContextFlags
/// </summary>
internal sealed class RootContext : ContextBase, IDisposable
{
const long MaximumV3StreamLength = 2147483648;

readonly IOContextFlags contextFlags;
readonly CfbBinaryWriter? writer;
readonly TransactedStream? transactedStream;
Expand Down Expand Up @@ -185,6 +187,9 @@ public void Flush()

public void ExtendStreamLength(long length)
{
if (Version is Version.V3 && length > MaximumV3StreamLength)
throw new IOException("V3 compound files are limited to 2 GB.");

if (Length < length)
Length = length;
}
Expand Down

0 comments on commit 99455c9

Please sign in to comment.