Compare commits

...

6 Commits

Author SHA1 Message Date
Adam Hathcock
1fddd102dc Merge pull request #1219 from adamhathcock/copilot/fix-nullreferenceexception-7z-extraction 2026-02-14 10:43:36 +00:00
Adam Hathcock
13fdb4d7ca add better length from master 2026-02-14 10:34:12 +00:00
Adam Hathcock
cdb13da054 Merge branch 'release' into copilot/fix-nullreferenceexception-7z-extraction 2026-02-14 10:22:41 +00:00
copilot-swe-agent[bot]
fb70f06fd4 Improve empty-stream test to verify HasStream == false entries
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-14 10:15:55 +00:00
copilot-swe-agent[bot]
31c6eb3b5c Fix NullReferenceException for 7z empty-stream entries
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-14 10:14:01 +00:00
copilot-swe-agent[bot]
eb7e55ac7d Initial plan 2026-02-14 10:08:28 +00:00
5 changed files with 78 additions and 8 deletions

View File

@@ -164,6 +164,12 @@ public partial class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, Sev
var folder = entry.FilePart.Folder;
// If folder is null (empty stream entry), return empty stream
if (folder is null)
{
return CreateEntryStream(Stream.Null);
}
// Check if we're starting a new folder - dispose old folder stream if needed
if (folder != _currentFolder)
{

View File

@@ -206,8 +206,22 @@ internal partial class SharpCompressStream : Stream, IStreamStack
throw new NotSupportedException();
}
public override long Length =>
_isPassthrough ? stream.Length : throw new NotSupportedException();
public override long Length
{
get
{
if (_isPassthrough)
{
return stream.Length;
}
if (_ringBuffer is not null)
{
return _ringBuffer.Length;
}
throw new NotSupportedException();
}
}
public override long Position
{

View File

@@ -216,9 +216,9 @@
"net10.0": {
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[10.0.0, )",
"resolved": "10.0.0",
"contentHash": "kICGrGYEzCNI3wPzfEXcwNHgTvlvVn9yJDhSdRK+oZQy4jvYH529u7O0xf5ocQKzOMjfS07+3z9PKRIjrFMJDA=="
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "sXdDtMf2qcnbygw9OdE535c2lxSxrZP8gO4UhDJ0xiJbl1wIqXS1OTcTDFTIJPOFd6Mhcm8gPEthqWGUxBsTqw=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
@@ -264,9 +264,9 @@
"net8.0": {
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[8.0.22, )",
"resolved": "8.0.22",
"contentHash": "MhcMithKEiyyNkD2ZfbDZPmcOdi0GheGfg8saEIIEfD/fol3iHmcV8TsZkD4ZYz5gdUuoX4YtlVySUU7Sxl9SQ=="
"requested": "[8.0.23, )",
"resolved": "8.0.23",
"contentHash": "GqHiB1HbbODWPbY/lc5xLQH8siEEhNA0ptpJCC6X6adtAYNEzu5ZlqV3YHA3Gh7fuEwgA8XqVwMtH2KNtuQM1Q=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",

View File

@@ -4,6 +4,7 @@ using System.Linq;
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Common;
using SharpCompress.Common.SevenZip;
using SharpCompress.Factories;
using SharpCompress.Readers;
using Xunit;
@@ -344,4 +345,53 @@ public class SevenZipArchiveTests : ArchiveTests
// The critical check: within a single folder, the stream should NEVER be recreated
Assert.Equal(0, streamRecreationsWithinFolder); // Folder stream should remain the same for all entries in the same folder
}
[Fact]
public void SevenZipArchive_EmptyStream_WriteToDirectory()
{
// This test specifically verifies that archives with empty-stream entries
// (files with size 0 and no compressed data) can be extracted without throwing
// NullReferenceException. This was previously failing because the folder was null
// for empty-stream entries.
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.EmptyStream.7z");
using var archive = SevenZipArchive.OpenArchive(testArchive);
var emptyStreamFileCount = 0;
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
// Verify this is actually an empty-stream entry (HasStream == false)
var sevenZipEntry = entry as SevenZipEntry;
if (sevenZipEntry?.FilePart.Header.HasStream == false)
{
emptyStreamFileCount++;
}
// This should not throw NullReferenceException
entry.WriteToDirectory(SCRATCH_FILES_PATH);
}
}
// Ensure we actually tested empty-stream entries
Assert.True(
emptyStreamFileCount > 0,
"Test archive should contain at least one empty-stream entry"
);
// Verify that empty files were created
var extractedFiles = Directory.GetFiles(
SCRATCH_FILES_PATH,
"*",
SearchOption.AllDirectories
);
Assert.NotEmpty(extractedFiles);
// All extracted files should be empty (0 bytes)
foreach (var file in extractedFiles)
{
var fileInfo = new FileInfo(file);
Assert.Equal(0, fileInfo.Length);
}
}
}

Binary file not shown.