Skip to content

Code Quality: Use temporary files to extract zip entries #17461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

seer-by-sentry[bot]
Copy link
Contributor

Resolved / Related Issues

To prevent extra work, all changes to the Files codebase must link to an approved issue marked as Ready to build. Please insert the issue number following the hashtag with the issue number that this Pull Request resolves.

Steps used to test these changes

Stability is a top priority for Files and all changes are required to go through testing before being merged into the repo. Please include a list of steps that you used to test this PR.

  1. Opened Files with a large zip archive.
  2. Extracted the zip archive.
  3. Verified that the extraction completed successfully without an OutOfMemoryException.
  4. Monitored memory usage during extraction to ensure it remained within acceptable limits.

Fixes FILES-APP-1Z5. The issue was that: Zip file operations load entire files/archives into memory, exhausting RAM and causing OutOfMemoryException.

  • Extracts zip entries to temporary files instead of memory streams to avoid memory issues with large files.
  • Uses FileOptions.DeleteOnClose to automatically delete the temporary file when the stream is closed.
  • Adds error handling to delete the temporary file if extraction fails.

This fix was generated by Seer in Sentry, triggered by Yair. 👁️ Run ID: 852921

Not quite right? Click here to continue debugging with Seer.

@yaira2 yaira2 requested a review from Copilot August 18, 2025 14:40
@yaira2 yaira2 changed the title Performance: Use temporary files to extract zip entries Code Quality: Use temporary files to extract zip entries Aug 18, 2025
@yaira2 yaira2 marked this pull request as ready for review August 18, 2025 14:45
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR addresses a critical memory issue in zip file operations by replacing in-memory extraction with temporary file-based extraction. The change prevents OutOfMemoryException when working with large zip archives by avoiding loading entire files into RAM.

  • Replaces MemoryStream usage with temporary file streams for zip entry extraction
  • Implements automatic cleanup of temporary files using FileOptions.DeleteOnClose and explicit cleanup in error scenarios
  • Applies the fix consistently across all zip operation methods (OpenAsync, OpenReadAsync, OpenSequentialReadAsync, CopyAsync, RenameAsync, DeleteAsync)

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

{
DisposeCallback = () =>
{
fileStream.Dispose();
Copy link
Preview

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling fileStream.Dispose() in the DisposeCallback is redundant and potentially harmful. The NonSeekableRandomAccessStreamForRead should handle disposal of its underlying stream, and calling Dispose() twice could cause ObjectDisposedException.

Suggested change
fileStream.Dispose();

Copilot uses AI. Check for mistakes.

{
DisposeCallback = () =>
{
fileStream.Dispose();
Copy link
Preview

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling fileStream.Dispose() in the DisposeCallback is redundant and potentially harmful. The NonSeekableRandomAccessStreamForRead should handle disposal of its underlying stream, and calling Dispose() twice could cause ObjectDisposedException.

Suggested change
fileStream.Dispose();

Copilot uses AI. Check for mistakes.

{
DisposeCallback = () =>
{
fileStream.Dispose();
Copy link
Preview

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling fileStream.Dispose() in the DisposeCallback is redundant and potentially harmful. The NonSeekableRandomAccessStreamForRead should handle disposal of its underlying stream, and calling Dispose() twice could cause ObjectDisposedException.

Suggested change
fileStream.Dispose();

Copilot uses AI. Check for mistakes.

await zipFile.ExtractFileAsync(entry.Index, tempStream);
}

using var fileStream = new FileStream(tempFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.DeleteOnClose);
Copy link
Preview

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using FileOptions.DeleteOnClose with a 'using' statement creates a race condition. The file will be deleted when the FileStream is disposed at the end of the using block, but the NonSeekableRandomAccessStreamForRead may still need access to it after this method returns.

Copilot uses AI. Check for mistakes.

catch
{
// Clean up temp file if extraction failed
try { IO.File.Delete(tempFile); } catch { }
Copy link
Preview

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The empty catch block silently swallows all exceptions when trying to delete the temporary file. Consider logging the exception or at least catching specific exceptions like FileNotFoundException or UnauthorizedAccessException to avoid hiding unexpected errors.

Suggested change
try { IO.File.Delete(tempFile); } catch { }
try { IO.File.Delete(tempFile); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"Failed to delete temp file '{tempFile}': {ex}"); }

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant