Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

⚠⚠⚠ ZIP FILE CORRUPTION WHEN USING DIRECT MODE ⚠⚠⚠

未关闭
#874 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
38/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
停滞
技术栈
csharp
领域
backend

调研方向

从 src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs 第 2861 行附近开始,跟踪直接模式下 BeginUpdate、delete 和 CommitUpdate 期间的 CopyEntryDirect。使用一个较小的第一个文件,后跟一个较大的文件,然后删除第一个文件来复现问题。完成的标准是:提交此更新时,如果源和目标 stream 重叠,archive 不再损坏。

由索引模型根据 Issue 内容生成。

描述

bug zip
Describe the bug

https://github.com/icsharpcode/SharpZipLib/blame/master/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs#L2861

This looks to me like a somewhat big oversight - it silently corrupts files and no warning nor error happens until it is too late.
After a few hours of debugging I feel like CopyEntryDirect is simply not functional if, for instance, one of the first few files of the ZipFile got deleted in a prior operation.

Let's put it this way - in direct mode, source stream and destination stream are the same.
That means writing on the destination is the same as writing on the source. You want to make extra sure you don't write over what you're going to read next. But if any file is deleted, this premise is broken - as deletions are treated, and copies are treated first, upon trying to copy the file SharpZipLib will happily overwrite the very file it's reading with itself.

Let's take an example, for instance the one I just spent a while looking into. A zip file with a 44 byte file, and then a 80kB file.
I decide to delete the first one. It has an offset of zero, and the next file has an offset of 44, because it's right after.

BeginUpdate => Delete => CommitUpdate

Upon commitment, updates are sorted, and the copy will now happen before the delete.
So this is what the library does - it takes the first update it has to handle, it's a copy! From <offset 44> to <wherever we are>. Since we have not done anything yet, <wherever we are> is offset 0. So, CopyEntryDirect copies byte 44<=>80044 to 0<=>80000.
There is no alignment, so just writing the "header" of that file we're copying, which totals 75 bytes, already overwrites the file itself. This causes massive, unrecoverable wreckage onto any zip file it touches!

This could maybe fixed with some minimum alignment the size of a "maximum zip header", or maybe by accepting some level of fragmentation in files and not moving stuff onto itself, or maybe temporarily copying the stuff to memory before committing it to file (not like the Safe mode, which renews the stream completely, something I cannot do in my project)

Sorry for the very long issue but I felt like this was important.

Reproduction Code

No response

Steps to reproduce

Add a few files in a zip using ZipFile, start with a tiny one (~40 bytes), give a long name to the others, then delete the first one you added.

Expected behavior

Something else than complete archive corurption

Operating System

Windows

Framework Version

.NET Framework 4.x, Unity

Tags

ZIP

Additional context

No response

主要语言
C#
星标
3.9k
派生
1k
PR 合并指标
30 天内没有已合并 PR

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

icsharpcode/SharpZipLib 的其他 Issue

查看 icsharpcode/SharpZipLib 的全部 Issue

相似的 Issue

更多 C# Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。