From 07b2d37a0c28c027fb7d151f1a5ea34c5a8a54fb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 22:35:11 +0000 Subject: [PATCH 1/6] Initial plan From b9470611ebcc927070b44bde8ec892c06404435a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 22:37:49 +0000 Subject: [PATCH 2/6] Initial commit - planning changes to TarExtractor error handling Co-authored-by: gfs <98900+gfs@users.noreply.github.com> --- nuget.config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nuget.config b/nuget.config index 227ad0ce..765346e5 100644 --- a/nuget.config +++ b/nuget.config @@ -1,7 +1,7 @@ - + - + - \ No newline at end of file + From 2b2a9c2ab33cb29bb2dcb54d59b5e9d5586d679b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 22:39:45 +0000 Subject: [PATCH 3/6] Fix TarExtractor to dispose backing stream and skip failed entries Co-authored-by: gfs <98900+gfs@users.noreply.github.com> --- RecursiveExtractor/Extractors/TarExtractor.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RecursiveExtractor/Extractors/TarExtractor.cs b/RecursiveExtractor/Extractors/TarExtractor.cs index 8553da07..de5228d5 100644 --- a/RecursiveExtractor/Extractors/TarExtractor.cs +++ b/RecursiveExtractor/Extractors/TarExtractor.cs @@ -62,6 +62,8 @@ public async IAsyncEnumerable ExtractAsync(FileEntry fileEntry, Extra catch (Exception e) { Logger.Debug(Extractor.FAILED_PARSING_ERROR_MESSAGE_STRING, ArchiveFileType.TAR, fileEntry.FullPath, tarEntry.Key, e.GetType()); + fs?.Dispose(); + continue; } var name = tarEntry.Key?.Replace('/', Path.DirectorySeparatorChar); if (string.IsNullOrEmpty(name)) @@ -132,6 +134,8 @@ public IEnumerable Extract(FileEntry fileEntry, ExtractorOptions opti catch (Exception e) { Logger.Debug(Extractor.FAILED_PARSING_ERROR_MESSAGE_STRING, ArchiveFileType.TAR, fileEntry.FullPath, tarEntry.Key, e.GetType()); + fs?.Dispose(); + continue; } var name = tarEntry.Key?.Replace('/', Path.DirectorySeparatorChar); if (string.IsNullOrEmpty(name)) From ea4d2a1d2e85416d3de747fc49509ea1e3c8208b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 22:40:58 +0000 Subject: [PATCH 4/6] Fix ZipExtractor to dispose backing stream and skip failed entries Co-authored-by: gfs <98900+gfs@users.noreply.github.com> --- RecursiveExtractor/Extractors/ZipExtractor.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/RecursiveExtractor/Extractors/ZipExtractor.cs b/RecursiveExtractor/Extractors/ZipExtractor.cs index 0c786230..c6d1b0fa 100644 --- a/RecursiveExtractor/Extractors/ZipExtractor.cs +++ b/RecursiveExtractor/Extractors/ZipExtractor.cs @@ -136,9 +136,10 @@ public async IAsyncEnumerable ExtractAsync(FileEntry fileEntry, Extra catch (Exception e) { Logger.Debug(Extractor.FAILED_PARSING_ERROR_MESSAGE_STRING, ArchiveFileType.ZIP, fileEntry.FullPath, zipEntry.Key, e.GetType()); + target?.Dispose(); + continue; } - target ??= new MemoryStream(); var name = zipEntry.Key?.Replace('/', Path.DirectorySeparatorChar) ?? ""; var newFileEntry = new FileEntry(name, target, fileEntry, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff); @@ -222,7 +223,7 @@ public IEnumerable Extract(FileEntry fileEntry, ExtractorOptions opti { governor.CheckResourceGovernor(zipEntry.Size); - using var fs = StreamFactory.GenerateAppropriateBackingStream(options, zipEntry.Size); + var fs = StreamFactory.GenerateAppropriateBackingStream(options, zipEntry.Size); try { @@ -232,6 +233,8 @@ public IEnumerable Extract(FileEntry fileEntry, ExtractorOptions opti catch (Exception e) { Logger.Debug(Extractor.FAILED_PARSING_ERROR_MESSAGE_STRING, ArchiveFileType.ZIP, fileEntry.FullPath, zipEntry.Key, e.GetType()); + fs?.Dispose(); + continue; } var name = zipEntry.Key?.Replace('/', Path.DirectorySeparatorChar) ?? ""; From 90261d1fef7a4252c14c4ddcb0031567886f0504 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 06:13:01 +0000 Subject: [PATCH 5/6] Use passthroughStream in ZipExtractor to reduce allocations Co-authored-by: gfs <98900+gfs@users.noreply.github.com> --- RecursiveExtractor/Extractors/ZipExtractor.cs | 2 +- nuget.config | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/RecursiveExtractor/Extractors/ZipExtractor.cs b/RecursiveExtractor/Extractors/ZipExtractor.cs index c6d1b0fa..d5b061ee 100644 --- a/RecursiveExtractor/Extractors/ZipExtractor.cs +++ b/RecursiveExtractor/Extractors/ZipExtractor.cs @@ -238,7 +238,7 @@ public IEnumerable Extract(FileEntry fileEntry, ExtractorOptions opti } var name = zipEntry.Key?.Replace('/', Path.DirectorySeparatorChar) ?? ""; - var newFileEntry = new FileEntry(name, fs, fileEntry, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff); + var newFileEntry = new FileEntry(name, fs, fileEntry, passthroughStream: true, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff); if (options.Recurse || topLevel) { diff --git a/nuget.config b/nuget.config index 765346e5..227ad0ce 100644 --- a/nuget.config +++ b/nuget.config @@ -1,7 +1,7 @@ - + - + - + \ No newline at end of file From 80f2f28079fb0c9488a75d779c458f3c4a526878 Mon Sep 17 00:00:00 2001 From: Giulia Stocco <98900+gfs@users.noreply.github.com> Date: Fri, 13 Feb 2026 21:22:35 -0800 Subject: [PATCH 6/6] Update RecursiveExtractor/Extractors/ZipExtractor.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- RecursiveExtractor/Extractors/ZipExtractor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RecursiveExtractor/Extractors/ZipExtractor.cs b/RecursiveExtractor/Extractors/ZipExtractor.cs index 002be391..4c619da7 100644 --- a/RecursiveExtractor/Extractors/ZipExtractor.cs +++ b/RecursiveExtractor/Extractors/ZipExtractor.cs @@ -141,7 +141,7 @@ public async IAsyncEnumerable ExtractAsync(FileEntry fileEntry, Extra } var name = zipEntry.Key?.Replace('/', Path.DirectorySeparatorChar) ?? ""; - var newFileEntry = new FileEntry(name, target, fileEntry, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff); + var newFileEntry = new FileEntry(name, target, fileEntry, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff, passthroughStream: true); if (options.Recurse || topLevel) {