From 46d480c9a1f60bcdd6c600611cb9e2eb4c11ccc6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 29 Nov 2025 14:06:03 +0000 Subject: [PATCH] Changes before error encountered Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com> --- src/SharpCompress/Readers/Zip/ZipReader.cs | 6 +++ .../SharpCompress.Test/Zip/ZipReaderTests.cs | 39 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/SharpCompress/Readers/Zip/ZipReader.cs b/src/SharpCompress/Readers/Zip/ZipReader.cs index 5e82479c..65566f8e 100644 --- a/src/SharpCompress/Readers/Zip/ZipReader.cs +++ b/src/SharpCompress/Readers/Zip/ZipReader.cs @@ -75,6 +75,12 @@ public class ZipReader : AbstractReader ); } break; + // DirectoryEntry headers in the central directory are intentionally skipped. + // In streaming mode, we can only read forward, and DirectoryEntry headers + // reference LocalEntry headers that have already been processed. The file + // data comes from LocalEntry headers, not DirectoryEntry headers. + // For multi-volume ZIPs where file data spans multiple files, use ZipArchive + // instead, which requires seekable streams. case ZipHeaderType.DirectoryEnd: { yield break; diff --git a/tests/SharpCompress.Test/Zip/ZipReaderTests.cs b/tests/SharpCompress.Test/Zip/ZipReaderTests.cs index c48d98f4..8373718d 100644 --- a/tests/SharpCompress.Test/Zip/ZipReaderTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipReaderTests.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using SharpCompress.Archives; using SharpCompress.Common; using SharpCompress.IO; @@ -397,4 +399,41 @@ public class ZipReaderTests : ReaderTests Assert.Equal("second.txt", reader.Entry.Key); Assert.Equal(197, reader.Entry.Size); } + + [Fact] + public void ZipReader_Returns_Same_Entries_As_ZipArchive() + { + // Verifies that ZipReader and ZipArchive return the same entries + // for standard single-volume ZIP files. Both process entries from + // LocalEntry headers, while ZipArchive also reads DirectoryEntry + // headers from the central directory. + var testFiles = new[] { "Zip.none.zip", "Zip.deflate.zip", "Zip.none.issue86.zip" }; + + foreach (var testFile in testFiles) + { + var path = Path.Combine(TEST_ARCHIVES_PATH, testFile); + + var readerKeys = new List(); + using (var stream = File.OpenRead(path)) + using (var reader = ZipReader.Open(stream)) + { + while (reader.MoveToNextEntry()) + { + readerKeys.Add(reader.Entry.Key!); + } + } + + var archiveKeys = new List(); + using (var archive = Archives.Zip.ZipArchive.Open(path)) + { + foreach (var entry in archive.Entries) + { + archiveKeys.Add(entry.Key!); + } + } + + Assert.Equal(archiveKeys.Count, readerKeys.Count); + Assert.Equal(archiveKeys.OrderBy(k => k), readerKeys.OrderBy(k => k)); + } + } }